絕對差不超過限制的最長連續子數組

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)
著做權歸做者全部。商業轉載請聯繫做者得到受權,非商業轉載請註明出處。
相關文章
相關標籤/搜索