原题地址(中等)

方法1—暴力(时间超限)

思路

首先想到的就是暴力,双重循环来尝试所有的可能。不过时间超限了。

代码

  1. class Solution {
  2. public:
  3. int longestSubarray(vector<int>& nums, int limit) {
  4. int n = nums.size(), ans = 0;
  5. if(!n) return 0;
  6. for(int i = 0; i < n; i++) {
  7. int maxVal = nums[i], minVal = nums[i];
  8. for(int j = i; j < n; j++) {
  9. if(nums[j] > maxVal) maxVal = nums[j];
  10. if(nums[j] < minVal) minVal = nums[j];
  11. if(maxVal - minVal <= limit) ans = max(ans, j - i + 1);
  12. }
  13. }
  14. return ans;
  15. }
  16. };

时空复杂度

1438. 绝对差不超过限制的最长连续子数组 - 图1

方法2—滑动窗口+有序集合

这道题其实是考察了对语言各种模板函数的运用程度。
c++的话用multiset或者map就很好做了。

思路

这个是看的官解,主要是利用了c++自带的红黑树1438. 绝对差不超过限制的最长连续子数组 - 图2。然后使用滑动窗口枚举每一个位置作为右端点,找到其对应的最靠左的左端点,满足区间中最大值与最小值的差不超过limit。

也可以用 map<int, int> ,map会对数据自动排序,内部也是红黑树。

代码

multiset

  1. class Solution {
  2. public:
  3. int longestSubarray(vector<int>& nums, int limit) {
  4. multiset<int> ms;
  5. int n = nums.size(), left = 0, right = 0, ans = 0;
  6. while(right < n) {
  7. ms.insert(nums[right]);
  8. while(*ms.rbegin() - *ms.begin() > limit)
  9. ms.erase(ms.find(nums[left++]));
  10. ans = max(ans, right - left + 1);
  11. right++;
  12. }
  13. return ans;
  14. }
  15. };

map

  1. class Solution {
  2. public:
  3. int longestSubarray(vector<int>& nums, int limit) {
  4. map<int, int> m;
  5. int n = nums.size(), left = 0, right = 0, ans = 0;
  6. while(right < n) {
  7. m[nums[right]]++;
  8. while(m.rbegin()->first - m.begin()->first > limit){
  9. m[nums[left++]]--;
  10. if(m[nums[left-1]] == 0) m.erase(nums[left-1]);
  11. }
  12. ans = max(ans, right - left + 1);
  13. right++;
  14. }
  15. return ans;
  16. }
  17. };

时空复杂度

时间1438. 绝对差不超过限制的最长连续子数组 - 图3 空间1438. 绝对差不超过限制的最长连续子数组 - 图4

方法3—滑动窗口+队列

思路

可用两个双端队列来存储最大最小值,不断更新,这样寻找子串的最大最小值直接取两个队列的头元素相减即可。
官解方法2

代码

  1. class Solution {
  2. public:
  3. int longestSubarray(vector<int>& nums, int limit) {
  4. deque<int> queMax, queMin;
  5. int n = nums.size(), left = 0, right = 0, ans = 0;
  6. while(right < n) {
  7. // 保证queMax的元素都比nums[right]大
  8. while(!queMax.empty() && queMax.back() < nums[right])
  9. queMax.pop_back();
  10. // 保证queMin的元素都比nums[right]小
  11. while(!queMin.empty() && queMin.back() > nums[right])
  12. queMin.pop_back();
  13. queMax.push_back(nums[right]);
  14. queMin.push_back(nums[right]);
  15. while(!queMax.empty() && !queMin.empty() && queMax.front() - queMin.front() > limit) {
  16. if(nums[left] == queMax.front()) queMax.pop_front();
  17. if(nums[left] == queMin.front()) queMin.pop_front();
  18. left++;
  19. }
  20. ans = max(ans, right - left + 1);
  21. right++;
  22. }
  23. return ans;
  24. }
  25. };

时空复杂度

均为1438. 绝对差不超过限制的最长连续子数组 - 图5