You are given an array of integers nums, there is a sliding window of size k which is moving from the very left of the array to the very right. You can only see the k numbers in the window. Each time the sliding window moves right by one position.
defmaxSlidingWindow(nums, k): ifnot nums: return [] res = [] max_heap = [] for i, num inenumerate(nums): # 将当前元素推入堆(Python 默认最小堆,用负数模拟最大堆) heapq.heappush(max_heap, (-num, i)) # 当窗口形成后(i >= k-1),开始计算窗口最大值 if i >= k - 1: # 移除堆顶中超出窗口范围的元素(延迟删除) while max_heap[0][1] <= i - k: heapq.heappop(max_heap) # 当前堆顶元素(取负数还原)即为窗口最大值 res.append(-max_heap[0][0]) return res
Time:O(Nk) (if we implement PQ by ourselves, it is O(N\log{k})) Space:O(k)
defmaxSlidingWindow(nums, k): res = [] que = deque() # 存储索引,保证 nums[que[i]] 单调递减 for i inrange(len(nums)): # 移除比当前元素小的所有元素(它们不可能是最大值) while que and nums[i] >= nums[que[-1]]: que.pop() que.append(i) # 移除超出窗口范围的元素 if que[0] == i - k: que.popleft() # 当窗口形成后(i >= k-1),记录最大值 if i >= k - 1: res.append(nums[que[0]]) return res
Time:O(N) since each element is processed (add/remove) at most twice. Space:O(k)
defquery(self, l, r): res = float('-inf') l += self.size # 定位到叶子节点 r += self.size while l <= r: if l % 2 == 1: # 左边界是右孩子,单独处理 res = max(res, self.tree[l]) l += 1 if r % 2 == 0: # 右边界是左孩子,单独处理 res = max(res, self.tree[r]) r -= 1 l //= 2# 移动到父节点 r //= 2 return res defupdate(self, i, value): i += self.size # 找到叶子节点 self.tree[i] = value # 向上更新父节点 while i > 1: i //= 2 self.tree[i] = max(self.tree[2 * i], self.tree[2 * i + 1]) classSolution:
defmaxSlidingWindow(self, nums: List[int], k: int) -> List[int]: ifnot nums: return [] st = SegmentTree(nums) res = [] for i inrange(len(nums) - k + 1): res.append(st.query(i, i + k - 1)) return res
classSparseTable: def__init__(self, nums): self.n = len(nums) self.k = math.floor(math.log2(self.n)) + 1if self.n > 0else0 self.st = [[0] * self.k for _ inrange(self.n)] # 初始化 for i inrange(self.n): self.st[i][0] = nums[i] # 动态规划预处理 for j inrange(1, self.k): for i inrange(self.n - (1 << j) + 1): self.st[i][j] = max(self.st[i][j-1], self.st[i + (1 << (j-1))][j-1]) defquery(self, l, r): length = r - l + 1 k = math.floor(math.log2(length)) returnmax(self.st[l][k], self.st[r - (1 << k) + 1][k])
defmaxSlidingWindow(nums, k): ifnot nums: return [] st = SparseTable(nums) res = [] for i inrange(len(nums) - k + 1): res.append(st.query(i, i + k - 1)) return res
defmaxSlidingWindow(self, nums: List[int], k: int) -> List[int]: n = len(nums) left_max = [0] * n right_max = [0] * n
for i inrange(n): j = n-1-i # 从左到右计算块内最大值 if i % k == 0: left_max[i] = nums[i] else: left_max[i] = max(left_max[i-1], nums[i]) # 从右到左计算块内最大值 if j == n - 1or (j + 1) % k == 0: right_max[j] = nums[j] else: right_max[j] = max(right_max[j+1], nums[j])
# 计算每个窗口的最大值 res = [] for i inrange(n - k + 1): j = i + k - 1 res.append(max(right_max[i], left_max[j])) return res
Time:O(N) Space:O(N)
2373 Largest Local Values in a Matrix
You are given an n x n integer matrix grid.
Generate an integer matrix maxLocal of size (n - 2) x (n - 2) such that:
maxLocal[i][j] is equal to the largest value of the 3 x 3 matrix in grid centered around row i + 1 and column j + 1.
In other words, we want to find the largest value in every contiguous 3 x 3 matrix in grid.
Return the generated matrix.
Example 1:
1 2 3 4
Input: grid = [[9,9,8,1],[5,6,2,6],[8,2,6,4],[6,2,2,2]] Output: [[9,9],[8,6]] Explanation: The diagram above shows the original matrix and the generated matrix. Notice that each value in the generated matrix corresponds to the largest value of a contiguous 3 x 3 matrix in grid.
Example 2:
1 2 3
Input: grid = [[1,1,1,1,1],[1,1,1,1,1],[1,1,2,1,1],[1,1,1,1,1],[1,1,1,1,1]] Output: [[2,2,2],[2,2,2],[2,2,2]] Explanation: Notice that the 2 is contained within every contiguous 3 x 3 matrix in grid.
Constraints:
n == grid.length == grid[i].length
3 <= n <= 100
1 <= grid[i][j] <= 100
暴力
1 2 3 4 5 6 7 8 9 10 11 12 13 14
defcal_max(self,grid,x,y): mx=0 for i inrange(x,x+3): for j inrange(y,y+3): mx = max(mx,grid[i][j]) return mx
deflargestLocal(self, grid: List[List[int]]) -> List[List[int]]: N = len(grid) res = [[0]*(N-2) for _ inrange(N-2)] for i inrange(N-2): for j inrange(N-2): res[i][j] = self.cal_max(grid,i,j) return res
单调队列
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
deflargestLocal(self, grid: List[List[int]]) -> List[List[int]]: n = len(grid) res = [[0]*(n-2) for _ inrange(n-2)] for i inrange(n): que = deque() for j inrange(n): whilelen(que)!=0and grid[i][j]>grid[i][que[-1]]: que.pop() que.append(j) if j>=2: val = grid[i][que[0]] for k inrange(i-2,i+1): if k >= 0and k < n - 2: res[k][j-2] = max(res[k][j-2],val) if que[0] <= j-2: que.popleft() return res
2444. Count Subarrays With Fixed Bounds
Hint
You are given an integer array nums and two integers minK and maxK.
A fixed-bound subarray of nums is a subarray that satisfies the following conditions:
The minimum value in the subarray is equal to minK.
The maximum value in the subarray is equal to maxK.
Return the number of fixed-bound subarrays.
A subarray is a contiguous part of an array.
Example 1:
1 2 3
Input: nums = [1,3,5,2,7,5], minK = 1, maxK = 5 Output: 2 Explanation: The fixed-bound subarrays are [1,3,5] and [1,3,5,2].
Example 2:
1 2 3
Input: nums = [1,1,1,1], minK = 1, maxK = 1 Output: 10 Explanation: Every subarray of nums is a fixed-bound subarray. There are 10 possible subarrays.
Constraints:
2 <= nums.length <= 105
1 <= nums[i], minK, maxK <= 106
暴力
1 2 3 4 5 6 7 8 9 10 11
defcountSubarrays(self, nums, minK, maxK): count = 0 for i inrange(len(nums)): mini = float('inf') maxi = float('-inf') for j inrange(i, len(nums)): mini = min(mini, nums[j]) maxi = max(maxi, nums[j]) if mini == minK and maxi == maxK: count += 1 return count
defcountSubarrays(self, nums: List[int], minK: int, maxK: int) -> int: res = 0 left = 0 q_min = deque() q_max = deque() for i inrange(len(nums)): ifnot minK<=nums[i]<=maxK: q_min.clear() q_max.clear() left = i+1 continue while q_max and nums[i]>=nums[q_max[-1]]: q_max.pop() q_max.append(i) while q_min and nums[i]<=nums[q_min[-1]]: q_min.pop() q_min.append(i) if nums[q_min[0]] == minK and nums[q_max[0]] == maxK: res+=min(q_min[0],q_max[0])-left+1 return res
Time:O(N) Space:O(N)
滑动窗口
感觉像单调队列的一种特殊情况
1 2 3 4 5 6 7 8 9
defcountSubarrays(self, nums: List[int], minK: int, maxK: int) -> int: res = 0 jbad = jmax = jmin = -1 for i,a inenumerate(nums): if a > maxK or a < minK: jbad=i //ifnot minK<=a<=maxK if a == minK: jmin = i if a == maxK: jmax = i res += max(0,min(jmax,jmin)-jbad) return res
Time:O(N) Space:O(1)
2762. Continuous Subarrays
You are given a 0-indexed integer array nums. A subarray of nums is called continuous if:
Let i, i + 1, …, j be the indices in the subarray. Then, for each pair of indices i <= i1, i2 <= j, 0 <= |nums[i1] - nums[i2]| <= 2.
Return the total number of continuous subarrays.
A subarray is a contiguous non-empty sequence of elements within an array.
Example 1:
1 2 3 4 5 6 7 8 9
Input: nums = [5,4,2,4] Output: 8 Explanation: Continuous subarray of size 1: [5], [4], [2], [4]. Continuous subarray of size 2: [5,4], [4,2], [2,4]. Continuous subarray of size 3: [4,2,4]. There are no subarrys of size 4. Total continuous subarrays = 4 + 3 + 1 = 8. It can be shown that there are no more continuous subarrays.
Example 2:
1 2 3 4 5 6 7
Input: nums = [1,2,3] Output: 6 Explanation: Continuous subarray of size 1: [1], [2], [3]. Continuous subarray of size 2: [1,2], [2,3]. Continuous subarray of size 3: [1,2,3]. Total continuous subarrays = 3 + 2 + 1 = 6.
Constraints:
1 <= nums.length <= 105
1 <= nums[i] <= 109
有序集合
1 2 3 4 5 6 7 8 9 10 11 12 13
defcontinuousSubarrays(self, nums: List[int]) -> int: ans = left = 0 cnt = Counter() for right, x inenumerate(nums): cnt[x] += 1 whilemax(cnt) - min(cnt) > 2: y = nums[left] cnt[y] -= 1 if cnt[y] == 0: del cnt[y] left += 1 ans += right - left + 1 return ans
Time:O(Nlogk)
Space:O(K)
堆
原理和单调队列差不多,但是单调队列自维护了单调递增、递减的顺序,因此效率率低于单调队列
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
classSolution: defcontinuousSubarrays(self, nums: List[int]) -> int: res = 0 left = 0 max_heap = [] min_heap = [] for right,num inenumerate(nums): heapq.heappush(max_heap,(-num,right)) heapq.heappush(min_heap,(num,right)) while left <= right and -max_heap[0][0] - min_heap[0][0] > 2: while max_heap and max_heap[0][1] <= left: heapq.heappop(max_heap) while min_heap and min_heap[0][1] <= left: heapq.heappop(min_heap) left+=1 res+=right-left+1 return res
for i inrange(len(nums)): # 维护 q_max(单调递减) while q_max and nums[i] > nums[q_max[-1]]: q_max.pop() q_max.append(i) # 维护 q_min(单调递增) while q_min and nums[i] < nums[q_min[-1]]: q_min.pop() q_min.append(i) # 如果当前窗口的 max - min > 2,移动左边界 left while nums[q_max[0]] - nums[q_min[0]] > 2: if q_max[0] == left: q_max.popleft() if q_min[0] == left: q_min.popleft() left += 1 # 以 nums[i] 结尾的满足条件的子数组数量 = i - left + 1 res += i - left + 1 return res
Time:O(N) Space:O(N)
1438.Longest Continuous Subarray With Absolute Diff Less Than or Equal to Limit
Given an array of integers nums and an integer limit, return the size of the longest non-empty subarray such that the absolute difference between any two elements of this subarray is less than or equal to limit.
Example 1:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
Input: nums = [8,2,4,7], limit = 4 Output: 2 Explanation: All subarrays are: [8] with maximum absolute diff |8-8| = 0 <= 4. [8,2] with maximum absolute diff |8-2| = 6 > 4. [8,2,4] with maximum absolute diff |8-2| = 6 > 4. [8,2,4,7] with maximum absolute diff |8-2| = 6 > 4. [2] with maximum absolute diff |2-2| = 0 <= 4. [2,4] with maximum absolute diff |2-4| = 2 <= 4. [2,4,7] with maximum absolute diff |2-7| = 5 > 4. [4] with maximum absolute diff |4-4| = 0 <= 4. [4,7] with maximum absolute diff |4-7| = 3 <= 4. [7] with maximum absolute diff |7-7| = 0 <= 4. Therefore, the size of the longest subarray is 2.
Example 2:
1 2 3
Input: nums = [10,1,2,4,7,2], limit = 5 Output: 4 Explanation: The subarray [2,4,7,2] is the longest since the maximum absolute diff is |2-7| = 5 <= 5.
deflongestSubarray(self, nums: List[int], limit: int) -> int: res = 0 q_max = deque() q_min = deque() left = 0 for right,num inenumerate(nums): while q_max and num>=nums[q_max[-1]]: q_max.pop() q_max.append(right) while q_min and num<=nums[q_min[-1]]: q_min.pop() q_min.append(right) while nums[q_max[0]] - nums[q_min[0]]>limit: left+=1 if q_max[0]<left: q_max.popleft() if q_min[0]<left: q_min.popleft() res=max(res,right-left+1) return res
Time O(N) Space O(N)
1425. Constrained Subsequence Sum
Given an integer array nums and an integer k, return the maximum sum of a non-empty subsequence of that array such that for every two consecutive integers in the subsequence, nums[i] and nums[j], where i < j, the condition j - i <= k is satisfied.
A subsequence of an array is obtained by deleting some number of elements (can be zero) from the array, leaving the remaining elements in their original order.
Example 1:
1 2 3
Input: nums = [10,2,-10,5,20], k = 2 Output: 37 Explanation: The subsequence is [10, 2, 5, 20].
Example 2:
1 2 3
Input: nums = [-1,-2,-3], k = 1 Output: -1 Explanation: The subsequence must be non-empty, so we choose the largest number.
Example 3:
1 2 3
Input: nums = [10,-2,-10,-5,20], k = 2 Output: 23 Explanation: The subsequence is [10, -2, -5, 20].
动态规划 oot
1 2 3 4 5 6 7 8 9 10 11 12 13
defconstrainedSubsetSum(self, nums: List[int], k: int) -> int: n = len(nums) dp = nums.copy() res = dp[0]
for i inrange(1, n): # 取前k个元素中的最大值,确保不越界 start = max(0, i - k) max_prev = max(dp[start:i], default=0) dp[i] += max(max_prev, 0) res = max(res, dp[i])
return res
单调栈优化DP
1 2 3 4 5 6 7 8 9 10 11 12
defconstrainedSubsetSum(self, nums: List[int], k: int) -> int: dp = nums.copy() q = deque() for i inrange(len(nums)): while q and q[0]<i-k: q.popleft() dp[i] += max(0,dp[q[0]] if q else0) while q and dp[q[-1]]<dp[i]: q.pop() q.append(i)