LeetCode 122. 买卖股票的最佳时机 II
题目链接:122. 买卖股票的最佳时机 II
思考:又是一道一眼动规的题目,但其实用贪心的思想会更巧妙一些。我们看一下示例一,在第 2 天(股票价格 = 1)的时候买入,在第 3 天(股票价格 = 5)的时候卖出,,这笔交易所能获得利润 = 5 - 1 = 4 。随后,在第 4 天(股票价格 = 3)的时候买入,在第 5 天(股票价格 = 6)的时候卖出, 这笔交易所能获得利润 = 6 - 3 = 3 。总利润为 4 + 3 = 7 。
那我们是不是可以将每天与前一天的利润差计算出来,然后将利润大于0的次数直接全部相加,就是这个数组所能获取的最大利润。
Python版本:
class Solution:
def maxProfit(self, prices: List[int]) -> int:
profit = []
for i in range(1, len(prices)):
profit.append(prices[i]-prices[i-1])
res = 0
for v in profit:
if v>0:
res += v
return res
时间复杂度: O ( n ) O(n) O(n),空间复杂度: O ( 1 ) O(1) O(1)
go版本:
func maxProfit(prices []int) int {
res := 0
n := len(prices)-1
profit := make([]int, n)
for i:=1; i<len(prices); i++ {
profit[i-1] = prices[i]-prices[i-1]
}
for i:=0; i<n; i++ {
if profit[i]>0 {
res += profit[i]
}
}
return res
}
LeetCode 55. 跳跃游戏
题目链接:55. 跳跃游戏
思考:看一下示例,我们发现一个现象:我们不需要知道我们从当前位置跳几步,我们只需要知道我们在当前位置能达到的最远距离即可(在这个点上贪心跟动规很相似),当最远距离大于等于最后一个索引位置就返回true,否则在遍历结束返回false。
Python版本:
class Solution:
def canJump(self, nums: List[int]) -> bool:
maxLen = 0
for i in range(len(nums)):
if i <= maxLen:
maxLen = max(maxLen, i+nums[i])
if maxLen >= len(nums)-1:
return True
return False
时间复杂度: O ( n ) O(n) O(n),空间复杂度: O ( 1 ) O(1) O(1)
go版本:
func canJump(nums []int) bool {
maxLen := 0
for i:=0; i<len(nums); i++ {
if i <= maxLen {
if nums[i]+i > maxLen {
maxLen = nums[i]+i
}
}
if maxLen >= len(nums)-1 {
return true
}
}
return false
}
LeetCode 45. 跳跃游戏 II
题目链接:45. 跳跃游戏 II
思考:此题看似与上一题类似,但实际上要难以实现的多,但跳跃问题最根本的还是看能覆盖到的最远距离。贪心的思路是局部最优:当前可移动距离尽可能多走,如果还没到终点,步数再加一。思路虽然是这样,但在写代码的时候还不能真的就在当前位置能走多远走多远,那样就不知道下一步最远能到哪里了(所以单单只有一个覆盖范围是不够的了,这个后续会细说)。
所以正确的做法是要从覆盖到的最远距离出发,不管怎么跳,覆盖范围内一定是可以跳到的,以最小的步数增加覆盖范围,并且在覆盖范围一旦能覆盖到终点时结束,得到的就是最小步数。
根据前文,单单只有一个覆盖范围是不够的了,所以这里需要统计两个覆盖范围,当前这一步的最大覆盖范围和下一步最大的覆盖范围。如果移动下标达到了当前这一步的最大覆盖最远距离了,并且还没有到终点,那么就必须再走一步来增加覆盖范围,直到覆盖范围覆盖了终点。
Python版本:
class Solution:
def jump(self, nums: List[int]) -> int:
curLen, nextLen = 0, 0
res = 0
n = len(nums)
for i in range(n):
nextLen = max(nextLen, nums[i]+i)
if i==curLen:
if i < n-1:
res += 1
curLen = nextLen
if nextLen >= n-1:
return res
else:
return res
return res
时间复杂度: O ( n ) O(n) O(n),空间复杂度: O ( 1 ) O(1) O(1)
go版本:
func jump(nums []int) int {
curLen := 0
nextLen := 0
minStep := 0
for i:=0; i<len(nums); i++ {
if nums[i]+i > nextLen {
nextLen = nums[i]+i
}
if i==curLen {
if i < len(nums)-1 {
minStep++
curLen = nextLen
if nextLen >= len(nums)-1 {
break
}
} else {
break
}
}
}
return minStep
}