LeetCode-121. 买卖股票的最佳时机(121-I, 122-II, 123-III)
一、121. 买卖股票的最佳时机
1. 简介
参考: https://blog.csdn.net/qq_43498345/article/details/128308298
这个是只允许买卖一次。可以使用贪心算法。
2. 代码实现
#include <stdio.h> #define INT_MAX ((int)(~0u >> 1)) #define ARRAY_SIZE(arr) (sizeof(arr)/sizeof(arr[0])) int min_val(int x, int y) { return x < y ? x : y; } int max_val(int x, int y) { return x > y ? x : y; } /* 股票只能买卖一次的,使用贪心算法,求左侧的最小值与右侧的最大值 */ int max_profit(int *prices, int sz) { int i; int min_price = INT_MAX; int max_profi = 0; for (i = 0; i < sz; i++) { min_price = min_val(min_price, prices[i]); //求最低价在前,已经可以表示买在前了 max_profi = max_val(max_profi, prices[i] - min_price); } return max_profi; } int main() { int prices[] = {7,1,5,3,6,4}; //5 匹配 //int prices[] = {7,6,4,3,1}; //0 匹配 printf("func1: max profit=%d\n", max_profit(prices, ARRAY_SIZE(prices))); //只单次买入卖出 return 0; }
二、122. 买卖股票的最佳时机 II
1. 简介
参考:https://blog.csdn.net/qq_43498345/article/details/128308263
这次是可以买卖多次。
使用动态规划来解决,动态规划6要素:
(1) 确定dp递归数组、数组元素含义、下标含义。
dp[i][j] 表示此状态下手里最多钱的数量,i表示第i天,j=0表示没有持有,j=1表示持有。
(2) 确定递推公式
dp[i][0] = max(dp[i-1][0], dp[i-1][1] - prices[i]) //第i天没有持有,取,之前一直没有持有,和之前持有状态但这一天把它卖了,的最大值。
dp[i][1] = max(dp[i-1][0] - prices[i], dp[i-1][1]) //第i天持有,取,之前一直没有持有但这一天买了,或之前一直是持有状态。
(3) dp数组如何初始化
可以看到与 dp[0][0] 和 dp[0][1] 有关。
dp[0][0] = 0; //假设一开始手里的钱数为0
dp[0][1] = -prices[0];
(4) 确定遍历顺序(从左到右/从右到左)
可以看到dp后一个与前一个有关,因此从左向右
(5) 确定返回值
(6) 举例推导dp数组。
2. 代码实现
#include <stdio.h> #define INT_MAX ((int)(~0u >> 1)) #define ARRAY_SIZE(arr) (sizeof(arr)/sizeof(arr[0])) int min_val(int x, int y) { return x < y ? x : y; } int max_val(int x, int y) { return x > y ? x : y; } /* 让自己的返回值变为最后操作的结果(dp[i][0] 表示持有,dp[i][1] 表示没有持有) */ int max_profit_2(int *prices, int sz) { int i, j; int dp[32][2] = {{0}}; dp[0][0] = -prices[0]; dp[0][1] = 0; for (i = 1; i < sz; i++) { dp[i][0] = max_val(dp[i-1][0], dp[i-1][1] - prices[i]); dp[i][1] = max_val(dp[i-1][1], dp[i-1][0] + prices[i]); } return dp[sz-1][1]; //最后卖出了是没有持有状态,尽量将最后的运算结果作为返回结果。 } int main() { int prices[] = {7,1,5,3,6,4}; //5 匹配 //int prices[] = {7,6,4,3,1}; //0 匹配 //printf("func1: max profit=%d\n", max_profit(prices, ARRAY_SIZE(prices))); //上题的只单次买入卖出一次 printf("func3: max profit=%d\n", max_profit_2(prices, ARRAY_SIZE(prices))); //本题执行了多次买入/卖出 return 0; }
注:可以看到 dp[i] 只依赖于 dp[i-1], 因此可以使用滚动数组来降低空间复杂度,通过 dp[i % 2][X] 和 dp[(i - 1) % 2][X] 来实现,保存推导关系的只需要一个2x2的数组即可。
三、123. 买卖股票的最佳时机 III
1. 简介
参考:https://blog.csdn.net/qq_43498345/article/details/128323095
这个限制了,最大买卖两次。
这里仍然通过动态规划实现,注意推导的6大步骤。
一天一共就有五个状态,
[0]. 没有操作
[1]. 第一次买入
[2]. 第一次卖出
[3]. 第二次买入
[4]. 第二次卖出
dp[i][j]中 i表示第i天,j为 [0 - 4] 五个状态,dp[i][j]表示第i天状态j所剩最大现金。
注意:dp[i][1],表示的是第i天,买入股票的状态,并不是说一定要第i天买入股票,这是很多同学容易陷入的误区。
2. 代码
#include <stdio.h> #define ARRAY_SIZE(arr) (sizeof(arr)/sizeof(arr[0])) int min_val(int x, int y) { return x < y ? x : y; } int max_val(int x, int y) { return x > y ? x : y; } #define PRICE_SIZE 8 int max_profit(int *prices, int sz) { int i; int dp[PRICE_SIZE][5] = {{0}}; if (sz == 0) return 0; dp[0][1] = dp[0][3] = -prices[0]; for (i = 1; i < sz; i++) { dp[i][0] = dp[i - 1][0]; /* 第i天没有操作沿用之前状态,与第i天执行了各种操作,取最大值. 可以看到每一步都与前一步有关 */ dp[i][1] = max_val(dp[i - 1][1], dp[i - 1][0] - prices[i]); //第一次买入必须在没有任何操作的基础上 dp[i][2] = max_val(dp[i - 1][2], dp[i - 1][1] + prices[i]); //第一次卖出必须在第一次买入的基础上 dp[i][3] = max_val(dp[i - 1][3], dp[i - 1][2] - prices[i]); //第二次买入必须在第一次卖出的基础上 dp[i][4] = max_val(dp[i - 1][4], dp[i - 1][3] + prices[i]); //第二次卖出必须在第二次买入的基础上 } return dp[sz - 1][4]; } int main() { int prices[] = {3,3,5,0,0,3,1,4}; //6 成立 //int prices[] = {7,6,4,3,1}; //0 成立 //int prices[] = {1,2,3,4,5}; //4 成立 //int prices[] = {1}; //0 成立 //int prices[] = {1, 9}; //8 成立 printf("max_profit=%d\n", max_profit(prices, ARRAY_SIZE(prices))); //6 return 0; }
posted on 2025-02-18 01:16 Hello-World3 阅读(6) 评论(0) 编辑 收藏 举报
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
2019-02-18 Android USB Host框架
2019-02-18 Android USB gadget框架学习笔记