LeetCode-题目整理【3】:买卖股票的最佳时机

这篇具有很好参考价值的文章主要介绍了LeetCode-题目整理【3】:买卖股票的最佳时机。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

买卖股票的最佳时机 都是求最大利润,但是在没有限制,如121和122,动态规划稍微复杂一些,建议不用,到最后两道难题,题目有限制,使用动态规划通过求解子问题的最优解来逐步求解原问题的最优解。文章来源地址https://www.toymoban.com/news/detail-819431.html

  1. 买卖股票的最佳时机 给定一个数组 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 的长度。

  1. 买卖股票的最佳时机 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 的长度。
  1. 买卖股票的最佳时机 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,即最大利润。
  1. 买卖股票的最佳时机 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],即为最大利润。

到了这里,关于LeetCode-题目整理【3】:买卖股票的最佳时机的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 力扣(Leetcode) 121. 买卖股票的最佳时机

    给定一个数组  prices  ,它的第  i  个元素  prices[i]  表示一支给定股票第  i  天的价格。 你只能选择  某一天  买入这只股票,并选择在  未来的某一个不同的日子  卖出该股票。设计一个算法来计算你所能获取的最大利润。 返回你可以从这笔交易中获取的最大利润。如

    2024年01月25日
    浏览(42)
  • [思维]LeetCode:121.买卖股票的最佳时机

      题目链接:121. 买卖股票的最佳时机 - 力扣(Leetcode)   分析:这里的数据大小为1e5,所以使用暴力会TLE. 思路:我们发现, 需要找到最大利润,其目标就是找到当前第i位后的最大值。换位思考,就是找到当前第i位前的最小值。

    2023年04月09日
    浏览(56)
  • leetcode-188-买卖股票的最佳时机 IV

    https://leetcode.cn/problems/best-time-to-buy-and-sell-stock-iv/description/

    2024年02月10日
    浏览(39)
  • leetcode 188. 买卖股票的最佳时机 IV

            这道题是 买卖股票的最佳时机III  的升级版,即买卖次数限制为k次,做法和上一篇如法炮制,直接看代码:

    2024年02月12日
    浏览(36)
  • 【LeetCode】买卖股票的最佳时机含冷冻期

    链接: 买卖股票的最佳时机含冷冻期 题目描述 算法分析 程序设计

    2024年02月13日
    浏览(40)
  • leetcode 121. 买卖股票的最佳时机 (贪心 + 动规

    贪心的思路: 得到最小值,再挨个用数组中的值减去最小值,最终值取一个最大的 动规的思路: 现在觉得做动规的关键点就是找出,当前的状态是否与之前的状态有关,也就是说:当前一般会有两种状态,具体哪一种为最优,需要依靠之前的状态及逆行推导。 比如说本题

    2024年02月02日
    浏览(43)
  • LeetCode:121.买卖股票的最佳时机——动态规划

    🍎道阻且长,行则将至。🍓 🌻算法,不如说它是一种思考方式🍀 算法专栏: 👉🏻123 关于动态规划:LeetCode:322. 零钱兑换——动态规划从案例入门 题目描述 :给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。 你只能选择 某一天 买入这只

    2023年04月17日
    浏览(37)
  • leetCode买卖股票的最佳时机II(题号122)

    122. 买卖股票的最佳时机 II 给你一个整数数组  prices  ,其中  prices[i]  表示某支股票第  i  天的价格。 在每一天,你可以决定是否购买和/或出售股票。你在任何时候  最多  只能持有  一股  股票。你也可以先购买,然后在  同一天  出售。 返回  你能获得的  最大  

    2024年02月12日
    浏览(30)
  • 【LeetCode】309. 买卖股票的最佳时机含冷冻期

    给定一个整数数组 prices ,其中第    prices[i]  表示第  i  天的股票价格 。​ 设计一个算法计算出最大利润。在满足以下约束条件下,你可以尽可能地完成更多的交易(多次买卖一支股票): 卖出股票后,你无法在第二天买入股票 (即冷冻期为 1 天)。 注意: 你不能同时参与

    2024年02月10日
    浏览(42)
  • 【LeetCode股票买卖系列:309. 最佳买卖股票时机含冷冻期 | 暴力递归=>记忆化搜索=>动态规划】

    🚀 算法题 🚀 🌲 算法刷题专栏 | 面试必备算法 | 面试高频算法 🍀 🌲 越难的东西,越要努力坚持,因为它具有很高的价值,算法就是这样✨ 🌲 作者简介:硕风和炜,CSDN-Java领域新星创作者🏆,保研|国家奖学金|高中学习JAVA|大学完善JAVA开发技术栈|面试刷题|面经八股文

    2024年02月02日
    浏览(43)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包