333 words
2 minutes
日拱两卒(三)
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 ans