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

题目

给你一个整数数组 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 ≤ n u m s . l e n g t h ≤ 1 0 5 1 \le nums.length \le 10^5 1nums.length105
1 ≤ n u m s [ i ] ≤ 1 0 9 1 \le nums[i] \le 10^9 1nums[i]109
0 ≤ l i m i t ≤ 1 0 9 0 \le limit \le 10^9 0limit109

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/longest-continuous-subarray-with-absolute-diff-less-than-or-equal-to-limit

题解

这是在Leetcode上经常使用的一个方法,就是滑动窗口,而现在我们要维持的是这个区间的最大值和最小值,并且 m a x V a l u e − m i n V a l u e ≤ l i m i t maxValue - minValue \le limit maxValueminValuelimit
对于如果维持滑动窗口上的极值问题常用的方法就是单调栈,即维持一个单调的栈的数据结构,保障入栈的元素不会破坏栈的单调性。现在我们需要两个单调栈,一个是递增的,一个是递减的。

对于入栈的元素,判断入栈的时候是否需要元素出栈
对于不符合条件的区间,从左到右减少区间的大小,对于不在区间的元素进行出栈。
和普通的栈不同的是,这个题的将不符合条件的元素出栈是在栈底出来的。

Go

func longestSubarray(nums []int, limit int) int {
    maxQue := make([]int,0)
    minQue := make([]int,0)
    left := 0
    result := 0
    n := len(nums)
    for i:=0;i<n;i++{
        for len(maxQue)!=0 && nums[maxQue[len(maxQue)-1]] < nums[i] {
            maxQue = maxQue[:len(maxQue)-1]
        }
        maxQue = append(maxQue, i)

        for len(minQue)!=0 && nums[minQue[len(minQue)-1]] > nums[i] {
            minQue = minQue[:len(minQue)-1]
        }
        minQue = append(minQue,i)

        for len(minQue) !=0  && len(maxQue) !=0 && nums[maxQue[0]] - nums[minQue[0]] > limit {
            if maxQue[0] <= left {
                maxQue = maxQue[1:]
            }
            if minQue[0] <= left {
                minQue = minQue[1:]
            }
            left ++ 
        }
        if result < i-left + 1 {
            result = i - left + 1
        }
    }
    return result
    
} 

Java

class Solution {
    public int longestSubarray(int[] nums, int limit) {
        Deque<Integer> maxQue = new LinkedList<>();
        Deque<Integer> minQue = new LinkedList<>();

        int result = 0;
        int start  = 0;
        for (int end = 0; end < nums.length;end++) {
            while(! maxQue.isEmpty() && nums[maxQue.peekLast()] < nums[end]) {
                maxQue.pollLast();
            }
            maxQue.add(end);

            while(!minQue.isEmpty() && nums[minQue.peekLast()] > nums[end]) {
                minQue.pollLast();
            }
            minQue.add(end);

            while(!maxQue.isEmpty() && !minQue.isEmpty() && nums[maxQue.peek()]-nums[minQue.peek()] > limit) {
                if(maxQue.peek() <= start) maxQue.poll();
                if(minQue.peek() <= start) minQue.poll();
                start++;
            }
            result = Math.max(result, end-start+1);
        }
        return result;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值