LeetCode 5402 - 绝对差不超过限制的最长连续子数组(周赛)

题目描述

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

解法一:滑窗(Python)

利用滑窗,记录窗口中的最小值和最大值,当新加入元素与最大值或最小值的绝对差大于限制值之后(我们需要记录是哪种情况的触发,是最大值的绝对差不符合,还是最小值的绝对差不符合,再或者两种情况都不符合),按照触发的情况找到窗口中不符合条件的元素下标(两种情况都不符合时,我们寻找最大下标),然后将窗口在此下标之前的元素全部弹出(包括下标所指的当前元素)。重复此过程,当窗口中的元素都符合条件时,再操作下一个新加入元素。

注意两种特殊情况的判定:

  • n u m s [ . . . ] nums[...] nums[...]只有一个元素时,直接返回1
  • n u m s [ . . . ] nums[...] nums[...]全是一个元素时,直接返回 l e n ( n u m s ) len(nums) len(nums)
class Solution:
    def longestSubarray(self, nums: List[int], limit: int) -> int:
        wmd, mmin, mmax, mmin_indx, mmax_indx, res = [nums[0]], nums[0], nums[0], 0, 0, 1
        if len(nums) == 1: return res
        for i in range(1, len(nums)):
            if nums[i] == nums[i-1]: res += 1
            else: break
        if res == len(nums): return res
        for i in range(1, len(nums)):
            wmd.append(nums[i])
            while abs(nums[i] - mmin) > limit or abs(nums[i] - mmax) > limit:
                if abs(nums[i] - mmin) > limit and abs(nums[i] - mmax) > limit:
                    mmin_indx = wmd.index(mmin) 
                    mmax_indx = wmd.index(mmax)
                    indx = max(mmin_indx, mmax_indx)
                    wmd = wmd[indx + 1:]
                    mmin, mmax = min(wmd), max(wmd)
                elif abs(nums[i] - mmin) > limit:
                    mmin_indx = wmd.index(mmin)
                    wmd = wmd[mmin_indx + 1:]
                    mmin, mmax = min(wmd), max(wmd)
                elif abs(nums[i] - mmax) > limit:
                    mmax_indx = wmd.index(mmax)
                    indx = min(mmax_indx, mmax_indx)
                    wmd = wmd[indx + 1:]
                    mmin, mmax = min(wmd), max(wmd)
            mmin, mmax = min(wmd), max(wmd)
            res = max(res, len(wmd))
        return res

换种写法

虽然我自己觉得我的代码没啥神操作的,但是lc平台上跑出来就莫名其妙双百了,我也很迷 Σ( ° △ °|||)︴

下面我们看看其他大佬的简便写法,但是思想都是一样的:利用滑窗,同时记录一些关键信息。

对于关键信息也就是最大值和最小值,那么思路有两:

  • 用容器自身的有序性
  • 用优先队列,也就是堆

第一个(C++):运用了 map 的有序性,来记录最大值和最小值

class Solution {
public:
    int longestSubarray(vector<int>& nums, int limit) {
        map<int, int> m;
        int ans = 0;
        int i = 0;
        for(int j=0;j<nums.size();j++)
        {
            m[nums[j]]++;

            // map是有序的,用最大值减去最小值
            while(m.rbegin()->first-m.begin()->first>limit)
            {
                m[nums[i]]--;
                if(m[nums[i]]==0) m.erase(nums[i]);
                i++;
            }
            ans = max(ans, j-i+1);
        }
        return ans;
    }
};

第二个(C++):运用 multiset

class Solution {
public:
    int longestSubarray(vector<int>& nums, int limit) {
        multiset<int> s;
        int ans = 0, i = 0;
        for(int j=0;j<nums.size();j++)
        {
            s.insert(nums[j]);
            while(*s.rbegin()-*s.begin()>limit)
            {
                s.erase(s.find(nums[i]));
                i++;
            }
            ans = max(ans, j-i+1);
        }
        return ans;
    }
};

第三个(Python):运用 heapq 建大顶堆和小顶堆

class Solution:
    def longestSubarray(self, nums: List[int], limit: int) -> int:
        mmax, mmin, left, res = [], [], 1, 0
        for right, num in enumerate(nums, 1):
            heapq.heappush(mmax, (-num, right)) # 大顶堆,但是heapq默认的是小顶堆,所以在num前取了负值
            heapq.heappush(mmin, (num, right)) 
            while -mmin[0][0] - mmax[0][0] >limit:
                # 删除left左边的元素
                while mmin[0][1] <= left: heapq.heappop(mmin)
                while mmax[0][1] <= left: heapq.heappop(mmax)
                left += 1
            res = max(res, right - left + 1)
        return res
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值