写代码的第二十四天
继续贪心!
122.买卖股票的最佳时机II
思路
贪心贪在哪里?就是每一次都要找到相邻两天差值为正,将这个数值加到最后的返回值中。
正确代码:
class Solution:
def maxProfit(self, prices: List[int]) -> int:
result = 0
for i in range(len(prices)):
if i > 0 and prices[i] - prices[i-1] > 0:
result += prices[i] - prices[i-1]
return result
55. 跳跃游戏
思路
不要纠结于每次到底走几步,要看覆盖范围,只要覆盖范围包括了数组的最大长度,那么就证明可以到达最后。
本题的局部最优解就是让每次都覆盖尽可能大的数组长度。
错误第一版:测试用例没过。我们发现下面这个代码中循环的长度事整个数组,在这个数组中是没有负数的,所以除了全零的情况,他都会输出True,因为cover一直在加,所以我们每次得到的是当前覆盖的位置再向下走能最大走多大,所以范围应该是count。同时还要注意一个问题,cover不是每次遍历之后都会比上一次大,所以要比较cover和上一次哪个大,留下大的那个。
class Solution:
def canJump(self, nums: List[int]) -> bool:
cover = 0
for i in range(len(nums)):
cover = i + nums[i]
if cover >= len(nums):
return True
return False
错误第二版:测试用例没通过。一个数字的时候没过。加一个判断条件。
class Solution:
def canJump(self, nums: List[int]) -> bool:
cover = 0
for i in range(len(nums)):
if i <= cover:
cover = max(cover,i + nums[i])
if cover >= len(nums):
return True
return False
错误第三版:测试用例没过【2,0,0】。因为cover是从下标为零开始的!!!!!!!!所以最后的比较是下标是否包含数组的最后一个下标len(nums)-1!!!!。
class Solution:
def canJump(self, nums: List[int]) -> bool:
cover = 0
if len(nums) == 1:
return True
for i in range(len(nums)):
if i <= cover:
cover = max(cover,i + nums[i])
if cover >= len(nums):
return True
return False
正确代码:
class Solution:
def canJump(self, nums: List[int]) -> bool:
cover = 0
if len(nums) == 1:
return True
for i in range(len(nums)):
if i <= cover:
cover = max(cover,i + nums[i])
if cover >= len(nums)-1:
return True
return False
45.跳跃游戏II
思路
上一个题的要求是只要看最后能不能到达终点即可,而这道题要求的是最少几步到。从下标为零开始走,查看每次的走过的覆盖范围,然后步数+1,如果当前的覆盖范围已经包含了数组最后一位那么结束,如果不包含那么要继续向前走。
错误第一版:测试用例未通过。【1,2,1,1,1】。在更新curdistance时,应该考虑跳到当前位置所需的步数,而不是只考虑当前位置能跳到的最远距离。此外,在每一步中,应该选择能跳的最远距离更新curdistance。
class Solution:
def jump(self, nums: List[int]) -> int:
result = 0
curdistance = 0
if len(nums) == 1:
return 0
for i in range(len(nums)):
curdistance = max(i+nums[i],curdistance)
result += 1
if curdistance >= len(nums) - 1:
return result
正确代码:每次cur之后都要知道下一次的位置在哪,如果说当前的cur位置不包括数组最后一位的话,那么就需要知道下一次的位置范围是什么,同时要步数加一。
class Solution:
def jump(self, nums: List[int]) -> int:
result = 0
curdistance = 0
nextdistance = 0
if len(nums) == 1:
return 0
for i in range(len(nums) - 1): # 注意这里遍历到倒数第二个位置就可以了
nextdistance = max(nextdistance, i + nums[i])
if i == curdistance: # 到达当前能跳到的最远位置时更新 curdistance
curdistance = nextdistance
result += 1
return result
1005.K次取反后最大化的数组和
思路
错误第一版:思路直接将数组从小到大排序,然后从下标为0开始选中k个数,进行操作,求和,最后的结果就是没考虑题中说的可以同一个数反复变换。。。
class Solution:
def largestSumAfterKNegations(self, nums: List[int], k: int) -> int:
nums = sorted(nums)
for i in range(k):
nums[i] = -nums[i]
return sum(nums)
错误第二版:测试用例没通过。因为没有在初始情况下排序!!!!如果k值小于数组中负数的个数!!!!!
class Solution:
def largestSumAfterKNegations(self, nums: List[int], k: int) -> int:
for i in range(len(nums)):
if nums[i] < 0 and k >= 0:
nums[i] = -nums[i]
k -= 1
nums = sorted(nums)
if k % 2 == 1:
nums[0] *= -1
return sum(nums)
正确代码:
class Solution:
def largestSumAfterKNegations(self, nums: List[int], k: int) -> int:
nums = sorted(nums)
for i in range(len(nums)):
if k > 0 and nums[i] < 0:
nums[i] = -nums[i]
k -= 1
if k % 2 == 1:
nums = sorted(nums)
nums[0] *= -1
return sum(nums)