貪心
(1)121. 買賣股票的最佳時機
第 i 天賣出的最大利潤,即在前面最低價的時候買入
class Solution:def maxProfit(self, prices: List[int]) -> int:min_price = prices[0]ans = 0for price in prices:ans = max(ans, price - min_price)min_price = min(min_price, price)return ans
(2)152. 乘積最大子數組 —— 美團一面
class Solution:def maxProduct(self, nums: List[int]) -> int:n = len(nums)f_max = [0] * nf_min = [0] * nf_max[0] = f_min[0] = nums[0]for i in range(1, n):x = nums[i]f_max[i] = max(f_max[i-1] * x, f_min[i-1] * x, x)f_min[i] = min(f_max[i-1] * x, f_min[i-1] * x, x)return max(f_max)
(3)55. 跳躍游戲
max_idx[i]
表示nums[0 : max_idx]
所有元素中可以到達的最遠位置- 所以只需逐個遍歷每個位置, 判斷從之前的位置開始跳能否到達該位置
class Solution:def canJump(self, nums: List[int]) -> bool:# max_idx[i] 表示 nums[0 : max_idx] 所有元素中可以到達的最遠位置# 所以只需逐個遍歷每個位置, 判斷從之前的位置開始跳能否到達該位置max_idx = 0 for i,v in enumerate(nums):if i > max_idx:return Falsemax_idx = max(max_idx, i + nums[i])return True
(4)45. 跳躍游戲 II
只在無法繼續走的時候才建橋,且建的是最遠的橋,這是所有方案中最優的。
只遍歷到 n-2 因為我們的邊界 cur_right,在遍歷到 n-2 后,更新后的 cur_right 一定是 > n-2的,所以一定大于等于 n-1
class Solution:def jump(self, nums: List[int]) -> int:# 只在無法繼續走的時候才建橋,且建的是最遠的橋,這是所有方案中最優的。ans = 0cur_right = 0 # 已構造橋的最遠端next_right = 0 # 下一座橋的最遠端for i in range(len(nums) - 1):next_right = max(next_right, i + nums[i])if cur_right == i:cur_right = next_rightans += 1return ans
(5)763. 劃分字母區間
「同一字母最多出現在一個片段中」
意味著,一個片段若要包含字母 a,那么所有的字母 a 都必須在這個片段中
利用合并區間的思想,s = a b a b c b a c a d e f e g d e h i j h k l i j
- a出現的區間為 [0,8]
- b出現的區間為 [1,5]
- c 出現的區間為 [4,7]
結合<45. 跳躍游戲 II>的思路,
- 區間右端點相當于當前點能到達的最遠位置,
- 如果這個最遠的位置都被前面最遠區間的最遠位置包含住了
- 那么這兩個區間需要合并為一個區間
當 end = i
時,說明從 strat 到 當前位置 i 中的所有元素的最遠區間就是當前位置
所以把當前位置劃分為一個區間
class Solution:def partitionLabels(self, s: str) -> List[int]:last = {v:i for i,v in enumerate(s)} # 每個字母最后出現的位置start = end = 0ans = []for i,v in enumerate(s):end = max(end, last[v])if end == i:ans.append(end-start+1)start = i + 1return ans