跳转至

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

问题描述#

给你一个整数数组 nums ,和一个表示限制的整数 limit,请你返回最长连续子数组的长度,该子数组中的任意两个元素之间的绝对差必须小于或者等于 limit

如果不存在满足条件的子数组,则返回 0

 

示例 1:

输入:nums = [8,2,4,7], limit = 4
输出:2 
解释:所有子数组如下:
[8] 最大绝对差 |8-8| = 0 <= 4.
[8,2] 最大绝对差 |8-2| = 6 > 4. 
[8,2,4] 最大绝对差 |8-2| = 6 > 4.
[8,2,4,7] 最大绝对差 |8-2| = 6 > 4.
[2] 最大绝对差 |2-2| = 0 <= 4.
[2,4] 最大绝对差 |2-4| = 2 <= 4.
[2,4,7] 最大绝对差 |2-7| = 5 > 4.
[4] 最大绝对差 |4-4| = 0 <= 4.
[4,7] 最大绝对差 |4-7| = 3 <= 4.
[7] 最大绝对差 |7-7| = 0 <= 4. 
因此,满足题意的最长子数组的长度为 2 。

示例 2:

输入:nums = [10,1,2,4,7,2], limit = 5
输出:4 
解释:满足题意的最长子数组是 [2,4,7,2],其最大绝对差 |2-7| = 5 <= 5 。

示例 3:

输入:nums = [4,2,2,2,4,4,2,2], limit = 0
输出:3

 

提示:

  • 1 <= nums.length <= 10^5
  • 1 <= nums[i] <= 10^9
  • 0 <= limit <= 10^9

解题思路#

满足条件的子数组中 最大值与最小值的差 不会超过 \(\texttt{limit}\),所以在加入一个新的元素后,如果条件变得不满足,可以依次删掉数组中左边的数,直到条件重新被满足。

所以关键是如何维护区间的最大值和最小值。

方法一:multiset#

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
class Solution {
public:
    int longestSubarray(vector<int>& nums, int limit) {
        multiset<int> q;
        int ans = 0, L = 0;

        for (auto x : nums) {
            q.emplace(x);
            while (*q.rbegin() - *q.begin() > limit) q.erase(q.find(nums[L++]));
            ans = max(ans, (int) q.size());
        }

        return ans;
    }
};

时间复杂度\(\mathcal{O}(n\log(n))\)
空间复杂度\(\mathcal{O}(n)\)

方法二:set#

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
class Solution {
public:
    int longestSubarray(vector<int>& nums, int limit) {
        auto cmp = [&] (int i, int j) {
            return nums[i] != nums[j] ? nums[i] < nums[j] : i < j;
        };
        set<int, decltype(cmp)> q(cmp);
        int n = nums.size(), ans = 0, L = 0;

        for (int i = 0; i < n; ++i) {
            q.emplace(i);
            while (nums[*q.rbegin()] - nums[*q.begin()] > limit) q.erase(L++);
            ans = max(ans, (int) q.size());
        }

        return ans;
    }
};

时间复杂度\(\mathcal{O}(n\log(n))\)
空间复杂度\(\mathcal{O}(n)\)

方法三:单调队列#

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class Solution {
public:
    int longestSubarray(vector<int>& nums, int limit) {
        deque<int> big, small;
        int n = nums.size(), ans = 0, L = 0;

        for (int i = 0; i < n; ++i) {
            while (!big.empty() && nums[i] > big.back()) big.pop_back();
            big.emplace_back(nums[i]);

            while (!small.empty() && nums[i] < small.back()) small.pop_back();
            small.emplace_back(nums[i]);

            while (big.front() - small.front() > limit) {
                if (big.front() == nums[L]) big.pop_front();
                if (small.front() == nums[L]) small.pop_front();
                ++L;
            }

            ans = max(ans, i - L + 1);
        }

        return ans;
    }
};

时间复杂度\(\mathcal{O}(n)\)
空间复杂度\(\mathcal{O}(n)\)

返回顶部

在手机上阅读