leetcode刷题笔记-Monotonic queue/Stack

2289. Steps to Make Array Non-decreasing

class Solution:
    def totalSteps(self, A: List[int]) -> int:
        # 5 3, 1 step for 3
        # 5 3 2, 1 step for 2
        # 5 3 2 4, 2 step for 4, 2 step is based on the max step of 3 and 2 plus 1
        # 9 5 6 2 7, 3 step for 7 and 3 is based on the max step of (5, 6, 2) + 1
        dp = [0] * len(A) # how many steps to eliminate cur val
        stack = []
        for i, a in enumerate(A):
            cur = 0
            while stack and a >= A[stack[-1]]:
                cur = max(cur, dp[stack.pop()])
            if stack:  # if there is still a larger number in the stack, means cur a can be elimiated
                dp[i] = cur + 1
            stack.append(i) 
        return max(dp)   

2104. Sum of Subarray Ranges

class Solution:
    def subArrayRanges(self, nums: List[int]) -> int:
        # https://leetcode.com/problems/sum-of-subarray-ranges/discuss/1979763/Python-Stack-O(n)-Solution-with-inline-explanation
        # the answer will be sum{ Max(subarray) - Min(subarray) } over all possible subarray
        # which decomposes to sum{Max(subarray)} - sum{Min(subarray)} over all possible subarray
        # so totalsum = maxsum - minsum
        # we calculate minsum and maxsum in two different loops
        
        n = len(nums)
        minSum = maxSum = 0
        stack = []
        
        # first calculate sum{ Min(subarray) } over all subarrays
        # sum{ Min(subarray) } = sum(f(i) * nums[i]) ; i=0..n-1
        # where f(i) is number of subarrays where nums[i] is the minimum value
        # f(i) = (i - index of the previous smaller value) * (index of the next smaller value - i)
        # minSum stack 要保持递增,最左边的是最小值
        for next_smaller in range(n+1):
            while stack and (next_smaller == n or nums[stack[-1]] > nums[next_smaller]):
                i = stack.pop()  # cur index
                pre_smaller = stack[-1] if stack else -1
                minSum += nums[i] * (i - pre_smaller) * (next_smaller - i)
            stack.append(next_smaller)
            
        # then calculate sum{ Max(subarray) } over all subarrays
        # sum{ Max(subarray) } = sum(f'(i) * nums[i]) ; i=0..n-1
        # where f'(i) is number of subarrays where nums[i] is the maximum value
        # f'(i) = (i - index of the previous larger value) - (index of the next larger value - i) 
        # 找最大值,就得递减,最左边的是最大值
        
        stack = []
        for next_larger in range(n+1):
            while stack and (next_larger == n or nums[stack[-1]] < nums[next_larger]):
                i = stack.pop()
                pre_larger = stack[-1] if stack else -1
                maxSum += nums[i] * (i - pre_larger) * (next_larger - i)
            stack.append(next_larger)
        
        return maxSum - minSum

239. Sliding Window Maximum

 https://www.youtube.com/watch?v=2SXqBsTR6a8

class Solution(object):
    def maxSlidingWindow(self, nums, k):
        """
        :type nums: List[int]
        :type k: int
        :rtype: List[int]
        """
        d = collections.deque()
        out = []
        
        for i, n in enumerate(nums):
            while d and nums[d[-1]] < n:
                d.pop()
                
            d.append(i)
            if d[0] == i - k:  # 存了K+1个元素了
                d.popleft()
            if i >= k - 1:
                out.append(nums[d[0]])
        return out

907. Sum of Subarray Minimums

    public int sumSubarrayMins(int[] A) {
        Stack<Integer> s = new Stack<>();
        int n = A.length, res = 0, mod = (int)1e9 + 7, j,k;
        for (int i = 0; i <= n; i++) {
            while (!s.isEmpty() && A[stack.peek()] > (i == n ? 0 : A[i])) {
                j = stack.pop();
                k = stack.isEmpty() ? -1 : stack.peek();
// i is right boundary   k is left boundary
                res = (res + A[j] * (i - j) * (j - k)) % mod; 
            }
            stack.push(i);
        }
        return res;
    }
class Solution:
    def sumSubarrayMins(self, A):
        res = 0
        stack = []  #  non-decreasing 
        A = [float('-inf')] + A + [float('-inf')]
        for i, n in enumerate(A):
            while stack and A[stack[-1]] > n:
                cur = stack.pop()
                res += A[cur] * (i - cur) * (cur - stack[-1]) 
            stack.append(i)
        return res % (10**9 + 7)

1438. Longest Continuous Subarray With Absolute Diff Less Than or Equal to Limit

class Solution(object):
    def longestSubarray(self, nums, limit):
        """
        :type nums: List[int]
        :type limit: int
        :rtype: int
        Monotonic Queue O(n)
        https://leetcode.com/problems/longest-continuous-subarray-with-absolute-diff-less-than-or-equal-to-limit/discuss/609743/Java-Detailed-Explanation-Sliding-Window-Deque-O(N)
        """
        max_deque, min_deque = deque(), deque()
        res, l = 1, 0
        for r in range(len(nums)):
            while max_deque and max_deque[-1] < nums[r]:  # max_queue 递减
                max_deque.pop()
            max_deque.append(nums[r])
            
            while min_deque and min_deque[-1] > nums[r]:  # max_queue 递增
                min_deque.pop()
            min_deque.append(nums[r])
            
            while max_deque[0] - min_deque[0] > limit:
                if max_deque[0] == nums[l]:
                    max_deque.popleft()
                    
                if min_deque[0] == nums[l]:
                    min_deque.popleft()
                
                l += 1
            res = max(res, r - l + 1)
        return res
            

1499. Max Value of Equation

class Solution:
    '''
    Because xi < xj,
yi + yj + |xi - xj| = (yi - xi) + (yj + xj)

So for each pair of (xj, yj),
we have xj + yj, and we only need to find out the maximum yi - xi.
To find out the maximum element in a sliding window,
we can use priority queue or stack.

    nlogn
    def findMaxValueOfEquation(self, A, k):
        q = []
        res = -float('inf')
        for x, y in A:
            while q and q[0][1] < x - k:
                heapq.heappop(q)
            if q: res = max(res, -q[0][0] + y + x)
            heapq.heappush(q, (x - y, x))
        return res
    '''
    def findMaxValueOfEquation(self, A, k):  # Monotonic queue 思路和上面一样
        q = collections.deque()
        res = -float('inf')
        for x, y in A:
            while q and q[0][1] < x - k:
                q.popleft()
            if q: res = max(res, q[0][0] + y + x)
            while q and q[-1][0] <= y - x:
                q.pop()
            q.append([y - x, x])
        return res

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值