122. 买卖股票的最佳时机 II
1. first idea
- 只要出现峰的拐点,就卖出.
- 只要出现谷的拐点,就买入。
- 如果最后一个是有股票扰卖出。
- 如果第一个点后是上坡就买入.
峰:
谷:
上坡起点:
2. doc
可以发现,其实我们需要收集每天的正利润就可以,收集正利润的区间,就是股票买卖的区间,而我们只需要关注最终利润,不需要记录区间。
那么只收集正利润就是贪心所贪的地方!
局部最优:收集每天的正利润,全局最优:求得最大利润。
class Solution:
def maxProfit(self, prices: List[int]) -> int:
max_profit = 0
for idx in range(1, len(prices)):
if prices[idx] > prices[idx - 1]:
max_profit += (prices[idx] - prices[idx - 1])
return max_profit
55. 跳跃游戏
1. first idea
Question: 如果我能跳3步,我该跳几步才能让后面的位置正好能跳到终点?
2. doc
其实这个也没必要纠结。
而是只要看每个位置能覆盖的范围:
- 搞清楚当前位置的覆盖范围,
- 在这个范围内所有点的覆盖范围中找到最大的那个覆盖范围,
- 到这个最大范围对应的起点,然后执行1.2.
- 直到范围能够囊括最后一个位置即可。
自己实现了一下:
class Solution:
def canJump(self, nums: List[int]) -> bool:
start_idx = 0
range_length = nums[start_idx]
while (start_idx + range_length) < (len(nums) - 1):
max_dis = 0
max_tmp_range = range_length
for dis in range(1, range_length + 1):
tmp_range = nums[start_idx + dis]
if (start_idx + max_dis + max_tmp_range) <= (start_idx + dis + tmp_range):
max_tmp_range = tmp_range
max_dis = dis
if max_dis == 0:
# 没有找到更远的范围。
# print(start_idx, max_dis, max_tmp_range, range_length)
return False
start_idx = start_idx + max_dis
range_length = max_tmp_range
return True
官方思路就是直接算一个从0开始的总得范围:
class Solution:
def canJump(self, nums: List[int]) -> bool:
if len(nums) == 1:
return True
start_idx = 0
range_length = nums[start_idx]
idx = 0
while idx < range_length + 1: # 这里不能用for循环,因为for边界值不会在循环体更新。
tmp_range = idx + nums[idx]
if tmp_range > range_length:
range_length = tmp_range
idx += 1
if range_length >= (len(nums) - 1):
return True
return False
45. 跳跃游戏 II
1. first idea
题目保证一定能跳到最后一个位置。
那我们每一步尽可能跳的最远,那就步数最少。
也就是在旧范围内能够为新范围贡献最大的那一步就是我们要选的。
那我们要如何找到这一步?
2. doc
实际上我们根本不需要找到是具体的哪一步贡献最大,而是只要还没覆盖到终点就加一步,因为没有这一步走不下去。
class Solution:
def jump(self, nums: List[int]) -> int:
if len(nums) == 1:
return 0
step_count = 0
cur_range = 0
next_range = 0
for idx in range(len(nums)):
next_range = max(idx + nums[idx], next_range)
if idx == cur_range: # 当前范围内能走到的最远的位置才开始更新范围,统计部署。
step_count += 1 # 他一定是从起点到达这里的,所以步数要加一。
cur_range = next_range # 我们需要更新范围了
if next_range >= len(nums) - 1:
# 如果新的范围覆盖了终点就结束,否则就需要继续走下一步。
break
return step_count