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

1. 题目来源

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

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;
    }
};
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Ypuyu

如果帮助到你,可以请作者喝水~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值