买卖股票的最佳时机 都是求最大利润,但是在没有限制,如121和122,动态规划稍微复杂一些,建议不用,到最后两道难题,题目有限制,使用动态规划通过求解子问题的最优解来逐步求解原问题的最优解。文章来源地址https://www.toymoban.com/news/detail-819431.html
- 买卖股票的最佳时机 给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。 你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。
返回你可以从这笔交易中获取的最大利润。如果你不能获取任何利润,返回 0 。
示例 1:
输入:[7,1,5,3,6,4]
输出:5
解释:在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。
注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格;同时,你不能在买入前卖出股票。
示例 2:
输入:prices = [7,6,4,3,1]
输出:0
解释:在这种情况下, 没有交易完成, 所以最大利润为 0。
func maxProfit(prices []int) int {
minPrice := prices[0]
maxProfit := 0
for i := 1; i < len(prices); i++ {
if prices[i] < minPrice {
minPrice = prices[i]
} else if prices[i] - minPrice > maxProfit {
maxProfit = prices[i] - minPrice
}
}
return maxProfit
}
//动态规划解答
func maxProfit(prices []int) int {
if len(prices) == 0 {
return 0
}
n := len(prices)
dp := make([]int, n)
dp[0] = 0
minPrice := prices[0]
for i := 1; i < n; i++ {
minPrice = min(minPrice, prices[i])
dp[i] = max(dp[i-1], prices[i]-minPrice)
}
return dp[n-1]
}
func min(a, b int) int {
if a < b {
return a
}
return b
}
func max(a, b int) int {
if a > b {
return a
}
return b
}
// 使用动态规划来解决这个问题,可以通过定义状态和状态转移方程来求解最大利润。
// 具体步骤如下:
// 定义状态:使用一个一维数组 dp 来表示在第 i 天的最大利润,dp[i] 表示第 i 天卖出股票所能获取的最大利润。
// 初始化状态:dp[0] 初始化为 0。
// 状态转移方程:对于第 i 天,可以选择卖出股票或者不卖出股票。如果选择卖出股票,则最大利润为 prices[i] - minPrice,其中 minPrice 表示前 i 天的最低价格。如果选择不卖出股票,则最大利润为前一天的最大利润 dp[i-1]。因此,状态转移方程为 dp[i] = max(dp[i-1], prices[i] - minPrice)。
// 更新最低价格:在更新状态之前,需要将当前价格 prices[i] 和之前的最低价格 minPrice 进行比较,更新最低价格为较小的那个。
// 遍历结束后,返回 dp[n-1],其中 n 表示数组 prices 的长度。
- 买卖股票的最佳时机 II
给你一个整数数组 prices ,其中 prices[i] 表示某支股票第 i 天的价格。
在每一天,你可以决定是否购买和/或出售股票。你在任何时候 最多 只能持有 一股 股票。你也可以先购买,然后在 同一天 出售。
返回 你能获得的 最大 利润 。
示例 1:
输入:prices = [7,1,5,3,6,4]
输出:7
解释:在第 2 天(股票价格 = 1)的时候买入,在第 3 天(股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5 - 1 = 4 。
随后,在第 4 天(股票价格 = 3)的时候买入,在第 5 天(股票价格 = 6)的时候卖出, 这笔交易所能获得利润 = 6 - 3 = 3 。
总利润为 4 + 3 = 7 。
示例 2:
输入:prices = [1,2,3,4,5]
输出:4
解释:在第 1 天(股票价格 = 1)的时候买入,在第 5 天 (股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5 - 1 = 4 。
总利润为 4 。
示例 3:
输入:prices = [7,6,4,3,1]
输出:0
解释:在这种情况下, 交易无法获得正利润,所以不参与交易可以获得最大利润,最大利润为 0 。
func maxProfit(prices []int) int {
if len(prices) <= 1 {
return 0
}
maxProfit := 0
for i := 1; i < len(prices); i++ {
if prices[i] > prices[i-1] {
maxProfit += prices[i] - prices[i-1]
}
}
return maxProfit
}
// 使用了贪心算法来解决问题,通过每次在价格上升时买入股票,价格下降时卖出股票,从而获取最大利润。
// 具体步骤如下:
// 初始化最大利润为 0。
// 遍历股票价格数组,从第 2 天开始。
// 如果当天的股票价格比前一天高,则将差值加入最大利润中。
// 遍历结束后,返回最大利润。
// 这种方法的思路是,当股票价格上涨时,我们可以在价格上涨期间多次买入和卖出,从而获取更多的利润。而当股票价格下跌时,我们不进行任何操作。
//动态规划
func maxProfit(prices []int) int {
if len(prices) == 0 {
return 0
}
n := len(prices)
buy := make([]int, n) // 当前持有股票的最大利润
sell := make([]int, n) // 当前不持有股票的最大利润
// 初始化第一天的情况
buy[0] = -prices[0]
sell[0] = 0
for i := 1; i < n; i++ {
// 当前持有股票的最大利润,要么继续保持前一天的状态,要么今天买入
buy[i] = max(buy[i-1], sell[i-1]-prices[i])
// 当前不持有股票的最大利润,要么继续保持前一天的状态,要么今天卖出
sell[i] = max(sell[i-1], buy[i-1]+prices[i])
}
// 最终返回最后一天不持有股票的最大利润
return sell[n-1]
}
func max(a, b int) int {
if a > b {
return a
}
return b
}
// 使用动态规划来解决。
// 具体步骤如下:
// 定义状态:使用两个一维数组 buy 和 sell 来分别表示在第 i 天持有股票和不持有股票时的最大利润。buy[i] 表示第 i 天持有股票时的最大利润,sell[i] 表示第 i 天不持有股票时的最大利润。
// 初始化状态:buy[0] 初始化为 -prices[0],表示第 0 天持有股票的最大利润;sell[0] 初始化为 0,表示第 0 天不持有股票的最大利润。
// 状态转移方程:对于第 i 天,如果选择持有股票,则最大利润为前一天持有股票的最大利润 buy[i-1] 或者前一天不持有股票的最大利润减去当天的股价 sell[i-1] - prices[i] 中的较大值;如果选择不持有股票,则最大利润为前一天不持有股票的最大利润 sell[i-1] 或者前一天持有股票的最大利润加上当天的股价 buy[i-1] + prices[i] 中的较大值。因此,状态转移方程为 buy[i] = max(buy[i-1], sell[i-1] - prices[i]),sell[i] = max(sell[i-1], buy[i-1] + prices[i])。
// 遍历数组结束后,返回 sell[n-1],其中 n 表示数组 prices 的长度。
- 买卖股票的最佳时机 III
给定一个数组,它的第 i 个元素是一支给定的股票在第 i 天的价格。
设计一个算法来计算你所能获取的最大利润。你最多可以完成 两笔 交易。
注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。
示例 1:
输入:prices = [3,3,5,0,0,3,1,4]
输出:6
解释:在第 4 天(股票价格 = 0)的时候买入,在第 6 天(股票价格 = 3)的时候卖出,这笔交易所能获得利润 = 3-0 = 3 。
随后,在第 7 天(股票价格 = 1)的时候买入,在第 8 天 (股票价格 = 4)的时候卖出,这笔交易所能获得利润 = 4-1 = 3 。
示例 2:
输入:prices = [1,2,3,4,5]
输出:4
解释:在第 1 天(股票价格 = 1)的时候买入,在第 5 天 (股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5-1 = 4 。
注意你不能在第 1 天和第 2 天接连购买股票,之后再将它们卖出。
因为这样属于同时参与了多笔交易,你必须在再次购买前出售掉之前的股票。
示例 3:
输入:prices = [7,6,4,3,1]
输出:0
解释:在这个情况下, 没有交易完成, 所以最大利润为 0。
示例 4:
输入:prices = [1]
输出:0
//动态规划
func maxProfit(prices []int) int {
if len(prices) == 0 {
return 0
}
buy1 := -prices[0]
sell1 := 0
buy2 := -prices[0]
sell2 := 0
for i := 1; i < len(prices); i++ {
buy1 = max(buy1, -prices[i])
sell1 = max(sell1, buy1+prices[i])
buy2 = max(buy2, sell1-prices[i])
sell2 = max(sell2, buy2+prices[i])
}
return sell2
}
func max(a, b int) int {
if a > b {
return a
}
return b
}
// 可以使用动态规划来解决。
// 具体步骤如下:
// 定义状态:使用四个变量 buy1、sell1、buy2、sell2 来分别表示第一次买入、第一次卖出、第二次买入、第二次卖出时的最大利润。
// 初始化状态:buy1 初始化为 -prices[0],表示第一次买入的最大利润;sell1、buy2、sell2 初始化为 0。
// 状态转移方程:对于第 i 天,我们可以选择买入第一次、卖出第一次、买入第二次、卖出第二次或者不进行任何操作。因此,状态转移方程为:
// buy1 = max(buy1, -prices[i]),第一次买入的最大利润为前一天买入的最大利润 buy1 或者今天买入的价格 -prices[i] 中的较大值。
// sell1 = max(sell1, buy1 + prices[i]),第一次卖出的最大利润为前一天卖出的最大利润 sell1 或者今天卖出的价格加上第一次买入的最大利润 buy1 + prices[i] 中的较大值。
// buy2 = max(buy2, sell1 - prices[i]),第二次买入的最大利润为前一天买入的最大利润 buy2 或者今天买入的价格 -prices[i] 加上第一次卖出的最大利润 sell1 中的较大值。
// sell2 = max(sell2, buy2 + prices[i]),第二次卖出的最大利润为前一天卖出的最大利润 sell2 或者今天卖出的价格加上第二次买入的最大利润 buy2 + prices[i] 中的较大值。
// 遍历结束后,返回 sell2,即最大利润。
- 买卖股票的最佳时机 IV
给你一个整数数组 prices 和一个整数 k ,其中 prices[i] 是某支给定的股票在第 i 天的价格。
设计一个算法来计算你所能获取的最大利润。你最多可以完成 k 笔交易。也就是说,你最多可以买 k 次,卖 k 次。
注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。
示例 1:
输入:k = 2, prices = [2,4,1]
输出:2
解释:在第 1 天 (股票价格 = 2) 的时候买入,在第 2 天 (股票价格 = 4) 的时候卖出,这笔交易所能获得利润 = 4-2 = 2 。
示例 2:
输入:k = 2, prices = [3,2,6,5,0,3]
输出:7
解释:在第 2 天 (股票价格 = 2) 的时候买入,在第 3 天 (股票价格 = 6) 的时候卖出, 这笔交易所能获得利润 = 6-2 = 4 。
随后,在第 5 天 (股票价格 = 0) 的时候买入,在第 6 天 (股票价格 = 3) 的时候卖出, 这笔交易所能获得利润 = 3-0 = 3 。
//动态规划
func maxProfit(k int, prices []int) int {
if k == 0 || len(prices) == 0 {
return 0
}
// 定义了一个辅助函数 maxProfitUnlimited 来计算不限制交易次数时的最大利润。
if k >= len(prices)/2 {
return maxProfitUnlimited(prices)
}
dp := make([][]int, len(prices))
for i := 0; i < len(prices); i++ {
dp[i] = make([]int, k+1)
}
for j := 1; j <= k; j++ {
buy := -prices[0]
for i := 1; i < len(prices); i++ {
dp[i][j] = max(dp[i-1][j], prices[i]+buy)
buy = max(buy, dp[i-1][j-1]-prices[i])
}
}
return dp[len(prices)-1][k]
}
// 和122. 买卖股票的最佳时机 II 使用贪心解法一样
// 定义了一个辅助函数 maxProfitUnlimited 来计算不限制交易次数时的最大利润。
func maxProfitUnlimited(prices []int) int {
profit := 0
for i := 1; i < len(prices); i++ {
if prices[i] > prices[i-1] {
profit += prices[i] - prices[i-1]
}
}
return profit
}
func max(x, y int) int {
if x > y {
return x
}
return y
}
// 可以使用动态规划来解决。
// 定义一个二维数组 dp,其中 dp[i][j] 表示在第 i 天进行了 j 笔交易的最大利润。
// 具体步骤如下:
// 初始化 dp 为一个大小为 (len(prices), k+1) 的二维数组,所有元素初始化为 0。
// 对于每一天 i,对于每一笔交易次数 j:
// 如果 j = 0,表示没有交易,利润为 0。
// 如果 i = 0,表示第一天,利润为 0。
// 否则,根据以下两种情况来更新 dp[i][j]:
// 第一种情况是在第 i 天不进行交易,即 dp[i][j] = dp[i-1][j]。
// 第二种情况是在第 i 天进行交易,即在前 i-1 天进行了 j-1 笔交易,然后在第 i 天买入股票,再在第 i 天卖出股票,即 dp[i][j] = dp[i-1][j-1] + prices[i] - prices[i-1]。
// 返回 dp[len(prices)-1][k],即为最大利润。
// 在这个解法中,首先判断特殊情况,如果 k = 0 或者 prices 数组为空,直接返回 0。
// 然后,初始化二维数组 dp,并且对于每一天和每一笔交易次数,根据上述的两种情况来更新 dp。
// 最后,返回 dp[len(prices)-1][k],即为最大利润。
文章来源:https://www.toymoban.com/news/detail-819431.html
到了这里,关于LeetCode-题目整理【3】:买卖股票的最佳时机的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!