1172 words
6 minutes
日拱两卒(三)
2026-07-13
80
划分字母区间。
把一个字符串分成尽可能多的区间,同一种字母必须出现在同一个区间。
预处理出来每个字母的最左和最右。
从前往后扫,维护必须延伸到的最右边。
class Solution: def partitionLabels(self, s: str) -> List[int]: n = len(s) seg = [[-1] * 2 for _ in range(26)]
for i, ch in enumerate(s): idx = ord(ch) - ord('a') if seg[idx][0] == -1: seg[idx][0] = i seg[idx][1] = i
ans = [] l = 0 r = seg[ord(s[0]) - ord('a')][1] i = l while True: if r >= n - 1: ans.append(n - 1 - l + 1) break if i > r: ans.append(r - l + 1) l = i r = seg[ord(s[i]) - ord('a')][1]
r = max(r, seg[ord(s[i]) - ord('a')][1]) i += 1
return ans79
跳跃游戏II。
问在nums上从0跳到n - 1的最小次数。每一次可以跳0到nums[i]之间任意远。
记忆化做法在Leetcode上没被卡。
但本质上和80 划分字母区间是同一道题。
维护当前区间的最远延申位置,每当指针越过这个边界,就完成一次切割或者跳跃。
class Solution: def jump(self, nums: List[int]) -> int: n = len(nums) if n == 1: return 0
right = [i + nums[i] for i in range(n)]
ans = 0 r = right[0] max_r = r i = 0
while True: if r >= n - 1: ans += 1 break
if i > r: ans += 1 r = max_r continue
max_r = max(max_r, right[i]) i += 1
return ans78
跳跃游戏。
上一题的Easy版,只问能否跳到,而不问最小跳跃次数。
class Solution: def canJump(self, nums: List[int]) -> bool: n = len(nums) r = 0 for i in range(n): r = max(r, i + nums[i]) if i >= r and r != n - 1: return False return True77
买卖股票的最佳时机。
知道每一天的股票价格,问最大可能利润。简单贪心。
class Solution: def maxProfit(self, prices: List[int]) -> int: n = len(prices)
rmax = [0] * (n + 1) rmax[n] = 0 for i in range(n - 1, -1, -1): rmax[i] = max(rmax[i + 1], prices[i])
ans = 0 for i in range(n): ans = max(ans, rmax[i] - prices[i]) return ans76
数据流的中位数。
往列表里不断添加元素,每添加一个元素就打印当前列表的中位数。
维护对顶堆,一个最大堆存前一半元素,一个最小堆存后一半元素,中位数只会与两个堆顶相关。
Python里有内置的堆相关内置函数,heappush是按堆的方式插元素,heappushpop是插完一个后再弹出堆顶。
默认是最小堆,想用最大堆就存相反数。
class MedianFinder:
def __init__(self): self.left = [] self.right = []
def addNum(self, num: int) -> None: if len(self.left) == len(self.right): add_to_left = heappushpop(self.right, num) heappush(self.left, -add_to_left) else: add_to_right = heappushpop(self.left, -num) heappush(self.right, -add_to_right)
def findMedian(self) -> float: if len(self.left) > len(self.right): return -self.left[0] return (-self.left[0] + self.right[0]) / 275
前 K 个高频元素。
哈希加桶排序。
class Solution: def topKFrequent(self, nums: List[int], k: int) -> List[int]: cnt = {} for num in nums: cnt[num] = cnt.get(num, 0) + 1 max_cnt = max(cnt.values())
buckets = [[] for _ in range(max_cnt + 1)] for x, c in cnt.items(): buckets[c].append(x)
ans = [] for bucket in reversed(buckets): ans += bucket if len(ans) == k: return ans74
数组中的第K大元素。
快速排序的思想+每次丢掉一半。
Python里写成这种三路归并的方法应该最好理解。
处理完有[l, lt - 1] < pivot, [lt, gt] = pivot, [gt + 1, r] > pivot。
class Solution: def quick_select(self, q, l, r, k) -> int: if l >= r: return q[l]
pivot = q[random.randint(l, r)]
lt, i, gt = l, l, r while i <= gt: if q[i] < pivot: q[i], q[lt] = q[lt], q[i] lt += 1 i += 1 elif q[i] > pivot: q[i], q[gt] = q[gt], q[i] gt -= 1 else: i += 1
if k < lt - l: return self.quick_select(q, l, lt - 1, k) if k <= gt - l: return pivot return self.quick_select(q, gt + 1, r, k - (gt - l + 1))
def findKthLargest(self, nums: List[int], k: int) -> int: n = len(nums) return self.quick_select(nums, 0, n - 1, n - k)73
柱状图重最大的矩形。
枚举高,单调栈算左右最长能延申到哪。
class Solution: def largestRectangleArea(self, h: List[int]) -> int: ans = 0 n = len(h)
stack = [] l = [-1] * n for i in range(n): while(stack and h[stack[-1]] >= h[i]): stack.pop() if stack: l[i] = stack[-1] stack.append(i)
stack = [] r = [n] * n for i in range(n - 1, -1, -1): while(stack and h[stack[-1]] >= h[i]): stack.pop() if stack: r[i] = stack[-1] stack.append(i)
for i in range(n): ans = max(ans, h[i] * ((r[i] - 1) - (l[i] + 1) + 1))
return ans72
每日温度。
给定每一天温度,问每一天的下一个更高温度出现在几天后。
找右边第一个更大的数,单调栈经典应用。
class Solution: def dailyTemperatures(self, temperatures: List[int]) -> List[int]: n = len(temperatures) ans = [0] * n stack = []
for i in range(n - 1, -1, -1): while stack and temperatures[stack[-1]] <= temperatures[i]: stack.pop() if stack: ans[i] = stack[-1] - i stack.append(i)
return ans71
字符串解码。
3[a]2[2[bc]]解析成aaabcbcbcbc。
简单递归模拟。
class Solution: def decodeString(self, s: str) -> str: if not s: return s
if s[0].isalpha(): return s[0] + self.decodeString(s[1:])
i = s.find('[') n = len(s) left = 1 for j in range(i + 1, n): if s[j] == '[': left += 1 elif s[j] == ']': left -= 1 if left == 0: return self.decodeString(s[i+1:j] * int(s[:i])) + self.decodeString(s[j+1:])