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

1.题目

给你一个整数数组 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:less

输入: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
输出:3ui

提示:指针

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

来源:力扣(LeetCode)
连接:https://leetcode-cn.com/problems/longest-continuous-subarray-with-absolute-diff-less-than-or-equal-to-limit
著做权归领扣网络全部。商业转载请联系官方受权,非商业转载请注明出处。索引

2.暴力破解的优化方法(双指针)

2.1原理

先来讲一下暴力破解,暴力破解就是逐个去比较,一旦出现不符合的时候,咱们便向前挪动,找出最长的子数组。队列

其实咱们不必依次去比较,咱们只要保证这个子数组中最大的值减去最小的值不大于limit,这样就能够保证子数组中全部的数都符合要求。

因此咱们一开始就记录最大值和最小值的数值和位置,左指针保持不动,让右指针先移动,只要右指针的值在最小值和最大值的中间,那么确定是符合的题意的,只有右指针指向的元素大于最大值或者小于最小值时,才可能会出现不符合题意的现象,一旦出现不符合题意的现象,就意味着最大值和最小值不符合,那么咱们判断是哪一个值靠前,咱们就让左指针移动过来,而后从新给最小值或者最大值赋值,接下来让右指针继续移动,若是仍不符合,左指针会继续移动,长度确定会小于咱们以前得出的最长的子数组,因此咱们一旦遇到不符合的状况,只要让左指针移动一次就好。若是遇到右指针等于最大值或最小值时,咱们也要从新给最大值或最小值赋值,这样就能够省下再寻找这个元素的时间。

2.2代码

class Solution {
public:
    int longestSubarray(vector<int>& nums, int limit) {
    	int left = 0, right = 0;
    	int max = nums[0], min = nums[0];
    	int maxp = 0, minp = 0;
    	int len = 0;
    	while(right < nums.size()) {
    		if(nums[right] >= max) {
    			max = nums[right];
    			maxp = right;
    		}
    		else if(nums[right] <= min) {
    			min = nums[right];
    			minp = right;
    		}
    		if(max - min <= limit) {
    			if(right - left + 1 > len)
    				len = right - left + 1;
    		}
    		else {
    			if(maxp > minp) {
    				left = minp + 1;
    				min = nums[left];
    				minp = left;
    				for(int i = left + 1; i <= right; i++) {
    					if(nums[i] <= min) {
    						min = nums[i];
    						minp = i;
    					}
    				}
    			}
    			else {
    				left = maxp + 1;
    				max = nums[left];
    				maxp = left;
    				for(int i = left + 1; i <= right; i++) {
    					if(nums[i] >= max) {
    						max = nums[i];
    						maxp = i;
    					}
    				}
    			}
    		}
    		right++;
    	}
    return len;
    }
};

3.滑动窗口+有序集合

3.1前置知识

平衡树:平衡树(Balance Tree,BT) 指的是,任意节点的子树的高度差都小于等于1。常见的符合平衡树的有,B树(多路平衡搜索树)、AVL树(二叉平衡搜索树)等。平衡树能够完成集合的一系列操做, 时间复杂度空间复杂度相对于“2-3树”要低,在完成集合的一系列操做中始终保持平衡,为大型数据库的组织、索引提供了一条新的途径

3.2原理

和我我的的暴力破解优化是相同的作法,保证最大值减去最小值不大于limit,在判断最大值和最小值的时候利用了平衡树的原理,在从新设置最大值和最小值的过程当中省去了时间,原来是n,利用平衡树是logn的时间复杂度,总时间复杂度是nlogn

3.3代码

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

做者:LeetCode-Solution
连接:https://leetcode-cn.com/problems/longest-continuous-subarray-with-absolute-diff-less-than-or-equal-to-limit/solution/jue-dui-chai-bu-chao-guo-xian-zhi-de-zui-5bki/
来源:力扣(LeetCode)
著做权归做者全部。商业转载请联系做者得到受权,非商业转载请注明出处。

4.滑动窗口+单调队列

4.1前置知识

单调队列:单调队列,即单调递减或单调递增的队列。使用频率不高,但在有些程序中会有非同寻常的做用。

4.2原理

道理仍是同样,依然是找最大值和最小值,在这里用了两个单调队列,来存储最大值和最小值,保证两个队列的第一个元素符合要求便可,不符合,开始让元素退出队列,直到符合条件为止,

4.3代码

class Solution {
public:
    int longestSubarray(vector<int>& nums, int limit) {
        deque<int> queMax, queMin;
        int n = nums.size();
        int left = 0, right = 0;
        int ret = 0;
        while (right < n) {
            while (!queMax.empty() && queMax.back() < nums[right]) {
                queMax.pop_back();
            }
            while (!queMin.empty() && queMin.back() > nums[right]) {
                queMin.pop_back();
            }
            queMax.push_back(nums[right]);
            queMin.push_back(nums[right]);
            while (!queMax.empty() && !queMin.empty() && queMax.front() - queMin.front() > limit) {
                if (nums[left] == queMin.front()) {
                    queMin.pop_front();
                }
                if (nums[left] == queMax.front()) {
                    queMax.pop_front();
                }
                left++;
            }
            ret = max(ret, right - left + 1);
            right++;
        }
        return ret;
    }
};

做者:LeetCode-Solution
连接:https://leetcode-cn.com/problems/longest-continuous-subarray-with-absolute-diff-less-than-or-equal-to-limit/solution/jue-dui-chai-bu-chao-guo-xian-zhi-de-zui-5bki/
来源:力扣(LeetCode)
著做权归做者全部。商业转载请联系做者得到受权,非商业转载请注明出处。
相关文章
相关标签/搜索