[LeetCode 周赛187] 3. 绝对差不超过限制的最长连续子数组(暴力、优先队列、常规解法)

文章目录

    • 1. 题目来源
    • 2. 题目说明
    • 3. 题目解析
      • 方法一:暴力投机+常规解法
      • 方法二:优先队列+双指针+巧妙解法

1. 题目来源

链接:5402. 绝对差不超过限制的最长连续子数组

2. 题目说明

[LeetCode 周赛187] 3. 绝对差不超过限制的最长连续子数组(暴力、优先队列、常规解法)_第1张图片
[LeetCode 周赛187] 3. 绝对差不超过限制的最长连续子数组(暴力、优先队列、常规解法)_第2张图片

3. 题目解析

方法一:暴力投机+常规解法

很暴力的一个暴力解法,加上一个特判就过了,若数组的最大项减去最小项还小于等于 limit 的话,说明应该返回整个数组长度。这个可有效避免重复项…但这个属实有点投机了,不推荐,但是真香 。

参见代码如下:

// 执行用时 :124 ms, 在所有 C++ 提交中击败了100.00%的用户
// 内存消耗 :30.3 MB, 在所有 C++ 提交中击败了100.00%的用户

class Solution {
public:
    int longestSubarray(vector<int>& nums, int limit) {
        int res = 0, c = nums[0], d = nums[0];
        for (auto e : nums) c = max(c, e), d = min(d, e);
        if (abs(c - d) <= limit) return nums.size();
        
        for (int i = 0; i < nums.size(); ++i) {
            int mx = nums[i], mi = nums[i], j = i;
            for (j; j < nums.size(); ++j) {
                mx = max(mx, nums[j]);
                mi = min(mi, nums[j]);
                if (abs(mx - mi) > limit) break;
            }
            res = max(res, j - i);
        }
        return res;
    }
};

方法二:优先队列+双指针+巧妙解法

这道题符合双指针思想,即固定 left 使 right 在条件下不断向右移动,移动到 n 或者未在条件内就跳出循环。采用两个优先队列来求出区间的最大、最小值。这个的时间复杂度为 O ( n l o g n ) O(nlogn) O(nlogn),并且采用优先队列求最大值就正常数据输入即可,求最小值时可以采用给数据乘负号的形式输入,输出时再乘负号即可。在此 make_pair 是一个函数,无法使用 typedef,就使用简单的宏替换即可,相当于字符串替换。但还是尽量少用宏定义吧。

不过这执行用时真的离谱了点…确实最后一个 case 很顶啊,不过这个解法确实能有效通过最后一个用例。

参见代码如下:

// 执行用时 :468 ms, 在所有 C++ 提交中击败了100.00%的用户
// 内存消耗 :34.7 MB, 在所有 C++ 提交中击败了100.00%的用户

typedef pair<int, int> PII;
#define MP(x, y) make_pair(x, y)
class Solution {
public:
    int longestSubarray(vector<int>& nums, int limit) {
        int ans = 0, n = nums.size();
        priority_queue<PII> mxq, miq;
        for (int i = 0, r = 0; i < n; ++i) {
            while (!mxq.empty() and mxq.top().second < i) mxq.pop();
            while (!miq.empty() and miq.top().second < i) miq.pop();
            int mx = 0, mi = 1e9 + 1;
            if (!mxq.empty()) mx = mxq.top().first;
            if (!mxq.empty()) mi = -miq.top().first;
            while (r < n and max(mx, nums[r]) - min(mi, nums[r]) <= limit) {
                mxq.push(MP(nums[r], r));
                miq.push(MP(-nums[r], r));
                mx = max(mx, nums[r]);
                mi = min(mi, nums[r]);
                ++r;
            }
            ans = max(ans, r - i);
        }
        return ans;
    }
};

你可能感兴趣的:(LeetCode周赛)