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