- 由于数字之间的关系,在题目中有限定递增等类似条件时,还可以通过单调栈等类似思想再对算法进行时间复杂度的降维优化
-
1964. 找出到每个位置为止最长的有效障碍赛跑路线
class Solution: def longestObstacleCourseAtEachPosition(self, obstacles: List[int]) -> List[int]: n = len(obstacles) st, dp = [], [] for i in range(n): if not st or st[-1] <= obstacles[i]: st.append(obstacles[i]) dp.append(len(st)) else: loc = bisect_right(st, obstacles[i]) dp.append(loc+1) st[loc] = obstacles[i] return dp
单调栈+二分查找(bisect模块)
-
2030. 含特定字母的最小子序列
class Solution: def smallestSubsequence(self, s: str, k: int, letter: str, repetition: int) -> str: n = len(s) right = [0] * (n+1) for i in range(n-1, -1, -1): right[i] = right[i+1] + (1 if s[i] == letter else 0) st = [] cur_repetition = 0 for i in range(n): while st and n - i + len(st) > k and st[-1] > s[i]: if st[-1] == letter and cur_repetition + right[i] <= repetition:break if st.pop() == letter:cur_repetition -= 1 if len(st) < k: if s[i] == letter or repetition - cur_repetition < k - len(st): if s[i] == letter:cur_repetition += 1 st.append(s[i]) return ''.join(st[:k])
限制条件单调栈
- 利用数字特性降维查询
-
class Solution: def minimumDifference(self, nums: [int]) -> int: n = len(nums) // 2 sum_nums = sum(nums) nums.sort() def helper() -> {}: onesl, onesr = collections.defaultdict(set), collections.defaultdict(set) for i in range(1 << n): cnt = 0 tmpl, tmpr = 0, 0 for j in range(n): if i & 1 << j: cnt += 1 tmpl += nums[j] tmpr += nums[n+j] onesl[cnt].add(tmpl) onesr[cnt].add(tmpr) return onesl, onesr ans = inf left_ones, right_ones = helper() mean_sum = sum_nums>>1 for i in range(n): lefts = sorted(left_ones[i]) rights = sorted(right_ones[n - i]) l, r = 0, len(rights) - 1 while l < len(lefts) and r >= 0: tmp = lefts[l] + rights[r] ans = min(ans, abs(sum_nums - 2 * tmp))
状态压缩dp取值
组合查询先排序成有序数组,再利用数字特性,双指针将组合从O(n**2)变为O(n)
- 动态变化数组求最值也可利用单调栈的思想,利用一个标记元素是否存在的数据结构来辅助维护堆
-
2034. 股票价格波动
class StockPrice: def __init__(self): self.stock = collections.defaultdict(int) self.time = -1 self.minhp = [] self.maxhp = [] self.stock_cnt = collections.defaultdict(int) def update(self, timestamp: int, price: int) -> None: if timestamp in self.stock:self.stock_cnt[self.stock[timestamp]] -= 1 self.stock[timestamp] = price self.time = max(self.time, timestamp) self.stock_cnt[price] += 1 while self.minhp and not self.stock_cnt[self.minhp[0]]: heapq.heappop(self.minhp) heapq.heappush(self.minhp, price) while self.maxhp and not self.stock_cnt[-self.maxhp[0]]: heapq.heappop(self.maxhp) heapq.heappush(self.maxhp, -price) def current(self) -> int: return self.stock[self.time] def maximum(self) -> int: return -self.maxhp[0] def minimum(self) -> int: return self.minhp[0]