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

给你一个整数数组 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 <= nums.length <= 10^5
  • 1 <= nums[i] <= 10^9
  • 0 <= limit <= 10^9

 

Method 1 sliding window

Seeking min/max for sliding window,O(n^2)

py

class Solution:
    def longestSubarray(self, nums: List[int], limit: int) -> int:
        curMax=curMin=nums[0]
        subArray=[]
        for num in nums:
            if abs(curMax-curMin)<=limit and abs(num-curMax)<=limit and abs(num-curMin)<=limit:
                curMax=max(curMax,num)
                curMin=min(curMin,num)
                subArray.append(num)
            else:
                subArray.append(num)
                subArray.pop(0)
                curMax=max(subArray)
                curMin=min(subArray)
        return len(subArray)

Java

class Solution {
    public int longestSubarray(int[] nums, int limit) {
        int curMax=nums[0];
        int curMin=nums[0];
        Queue<Integer> subArray=new LinkedList<>();
        for(int num:nums){
            if(Math.abs(curMax-curMin)<=limit&&Math.abs(num-curMax)<=limit&&Math.abs(num-curMin)<=limit){
                curMax=Math.max(curMax,num);
                curMin=Math.min(curMin,num);
                subArray.offer(num);
            }
            else{
                subArray.offer(num);
                subArray.poll();
                curMax=Collections.max(subArray);
                curMin=Collections.min(subArray);
            }
        } 
        return subArray.size();
    }
}

Method 2 use priority queue or deque

Time O(N)
Space O(N)

py_0

class Solution:
    def longestSubarray(self, nums: List[int], limit: int) -> int:
        res=1
        l=0
        maxd=deque()
        mind=deque()
        for r,num in enumerate(nums):
            # sliding window max/min
            while maxd and maxd[-1]<num:maxd.pop()
            while mind and mind[-1]>num:mind.pop()
            maxd.append(num)
            mind.append(num)
            # Pop out the front one by one
            while maxd and mind and maxd[0]-mind[0]>limit:
                if maxd[0]==nums[l]:maxd.popleft()
                if mind[0]==nums[l]:mind.popleft()
                l+=1
            res=max(res,r-l+1)
        return res

py_1

class Solution:
    def longestSubarray(self, nums: List[int], limit: int) -> int:
        i=0
        maxd=deque()
        mind=deque()
        for num in nums:
            while maxd and maxd[-1]<num:maxd.pop()
            while mind and mind[-1]>num:mind.pop()
            maxd.append(num)
            mind.append(num)
            if maxd[0]-mind[0]>limit:
                if maxd[0]==nums[i]:maxd.popleft()
                if mind[0]==nums[i]:mind.popleft()
                i+=1
        return len(nums)-i

Java

class Solution {
    public int longestSubarray(int[] nums, int limit) {
        Deque<Integer> maxd = new ArrayDeque<>();
        Deque<Integer> mind = new ArrayDeque<>();
        int i = 0, j;
        for (j = 0; j < nums.length; j++) {
            while (!maxd.isEmpty() && maxd.peekLast() < nums[j]) maxd.pollLast();
            while (!mind.isEmpty() && mind.peekLast() > nums[j]) mind.pollLast();
            maxd.add(nums[j]);
            mind.add(nums[j]);
            if (maxd.peek() - mind.peek() > limit) {
                if (maxd.peek() == nums[i]) maxd.poll();
                if (mind.peek() == nums[i]) mind.poll();
                i++;
            }
        }
        return j - i;
    }
}

cpp

class Solution {
public:
    int longestSubarray(vector<int>& nums, int limit) {
        deque<int> maxd,mind;
        int i = 0, j;
        for (j = 0; j < nums.size(); j++) {
            while (!maxd.empty() && maxd.back() < nums[j]) maxd.pop_back();
            while (!mind.empty() && mind.back() > nums[j]) mind.pop_back();
            maxd.push_back(nums[j]);
            mind.push_back(nums[j]);
            if (maxd.front() - mind.front() > limit) {
                if (maxd.front() == nums[i]) maxd.pop_front();
                if (mind.front() == nums[i]) mind.pop_front();
                i++;
            }
        }
        return j - i;
    }
};

 

Method 3 binary search and remove

Keep an increasing list q.
Binary insert the current element.
If

q[-1]-q[0]>limit

,
binary search the position of  nums[i] and remove it from the list.

 

Time O(N^2)
Space O(N)

class Solution:
    def longestSubarray(self, nums: List[int], limit: int) -> int:
        i=0
        q=[]
        for j in range(len(nums)):
            bisect.insort(q,nums[j])
            if q[-1]-q[0]>limit:
                q.pop(bisect.bisect(q,nums[i])-1)
                i+=1    
        return j-i+1

Method 4 use two heaps

Time O(NogN)
Space O(N)

class Solution:
    def longestSubarray(self, nums: List[int], limit: int) -> int:
        maxq, minq = [], []
        res = i = 0
        for j, a in enumerate(nums):
            heapq.heappush(maxq, [-a, j])
            heapq.heappush(minq, [a, j])
            while -maxq[0][0] - minq[0][0] > limit:
                i = min(maxq[0][1], minq[0][1]) + 1
                while maxq[0][1] < i: heapq.heappop(maxq)
                while minq[0][1] < i: heapq.heappop(minq)
            res = max(res, j - i + 1)
        return res

Method 5 use TreeMap

Use one tree map can easily get the maximum and the minimum at the same time.
In java, we can use TreeMap to count elements.
In cpp, it suports multi treeset, that's even better.

 

Time O(NogN)
Space O(N)

 

Java

class Solution {
    public int longestSubarray(int[] nums, int limit) {
        int i=0,j;
        TreeMap<Integer,Integer> m=new TreeMap<>();
        for(j=0;j<nums.length;j++){
            m.put(nums[j],1+m.getOrDefault(nums[j],0));
            if(m.lastEntry().getKey()-m.firstEntry().getKey()>limit){
                m.put(nums[i],m.get(nums[i])-1);
                if(m.get(nums[i])==0)
                    m.remove(nums[i]);
                i++;
            }
        }
        return j-i;
    }
}

cpp

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

 

 

reference:https://leetcode.com/problems/longest-continuous-subarray-with-absolute-diff-less-than-or-equal-to-limit/discuss/609771/JavaC%2B%2BPython-Deques-O(N)

 

 
posted @ 2021-02-21 13:30  XXXSANS  阅读(115)  评论(0编辑  收藏  举报