前言
思路及算法思维,指路 代码随想录。
题目来自 LeetCode。
day 46,周六,坚持很困难~
题目详情
[121] 买卖股票的最佳时机
题目描述
解题思路
前提:买入和卖出非同一天,且只可买卖一次
思路:贪心, 左侧最小值买入, 取其后最大值卖出;动态规划: dp[i][0]: 第i天不持有股票, dp[i][1]: 第i天持有股票 时的最大利润
重点:动态规划的推导公式,及初始化
代码实现
C语言
贪心
// 贪心: 左侧最小值买入, 取其后最大值卖出
int minFun(int p1, int p2)
{
return p1 < p2 ? p1 : p2;
}
int maxFun(int p1, int p2)
{
return p1 > p2 ? p1 : p2;
}
int maxProfit(int* prices, int pricesSize) {
int low = 10001;
int result = 0;
for (int i = 0; i < pricesSize; i++) {
low = minFun(low, prices[i]);
result = maxFun(result, prices[i] - low);
}
return result;
}
动态规划
// 动态规划: dp[i][0]: 第i天不持有股票, dp[i][1]: 第i天持有股票 时的最大利润
// dp[i][0]分为两种情况:股票未持有股票或之前已卖出,维持未持有现状; 股票当天卖出.
// dp[i][0] = max(dp[i - 1][0], dp[i - 1][1] + prices[i])
// dp[i][1]分为两种情况: 之前买入股票,一直未卖出, 维持持有现状;当天买入股票
// dp[i][1] = max(dp[i - 1][1], -prices[i])
int maxFun(int p1, int p2)
{
return p1 > p2 ? p1 : p2;
}
int maxProfit(int* prices, int pricesSize) {
int dp[pricesSize][2];
if (pricesSize == 1) {
return 0;
}
// dp初始化
dp[0][0] = 0;
dp[0][1] = 0 - prices[0];
// 前向后遍历
for (int i = 1; i < pricesSize; i++) {
dp[i][0] = maxFun(dp[i - 1][0], dp[i - 1][1] + prices[i]);
dp[i][1] = maxFun(dp[i - 1][1], 0 - prices[i]);
}
return dp[pricesSize - 1][0];
}
[122] 买卖股票的最佳时机II
题目描述
解题思路
前提:买入和卖出可同一天,且可买卖多次
思路:贪心, 把利润分解为每天为单位的维度,只统计正利润部分;动态规划: dp[i][0]: 第i天不持有股票的最多现金, dp[i][1]: 第i天持有股票的最多现金
重点:动态规划的推导公式,及初始化
代码实现
C语言
贪心
// 把利润分解为每天为单位的维度,只统计正利润部分
int maxProfit(int* prices, int pricesSize) {
int max = 0;
for (int i = 1; i < pricesSize; i++) {
if (prices[i] > prices[i - 1]) {
max += (prices[i] - prices[i - 1]);
}
}
return max;
}
动态规划
// 动态规划 dp[i][0]: 第i天不持有股票的最多现金; dp[i][1]: 第i天持有股票的最多现金
// dp[i][0] 两种情况: 维持第i-1天的不持有股票的情况; 第i-1天持有股票第i天卖掉
// dp[i][0] = max(dp[i-1][0], dp[i-1][1] + prices[i])
// dp[i][1] 两种情况: 维持第i-1天持有股票的情况; 第i-1天不持有股票第i天购入股票
// dp[i][1] = max(dp[i-1][1], dp[i-1][0] - prices[i])
// 取dp[i][0]和dp[i][1]中的最大值, dp[i][0]一定大于dp[i][1]
int maxFun(int p1, int p2)
{
return p1 > p2 ? p1 : p2;
}
int maxProfit(int* prices, int pricesSize) {
int dp[pricesSize][2];
// dp数组初始化
dp[0][0] = 0;
dp[0][1] = 0 - prices[0];
// 遍历
for (int i = 1; i < pricesSize; i++) {
dp[i][0] = maxFun(dp[i - 1][0], dp[i - 1][1] + prices[i]);
dp[i][1] = maxFun(dp[i - 1][1], dp[i - 1][0] - prices[i]);
}
return dp[pricesSize - 1][0];
}
[123] 买卖股票的最佳时机III
题目描述
解题思路
前提:买入和卖出可同一天,且至多可买卖2次
思路:动态规划: 分为5种状态, 取最大值。
重点:情况的列举,动态规划的推导公式,及初始化
代码实现
C语言
动态规划
// 动态规划 分为5种状态, 取最大值
// dp[i][0]: 不持有股票的最大现金, dp[i][0] = 0;
// dp[i][1]: 第一次买入股票持有的最大现金, dp[i][1] = max(dp[i-1][1], dp[i-1][0]-prices[i])
// dp[i][2]: 第一次卖出交票持有的最大现金, dp[i][2] = max(dp[i-1][2], dp[i-1][1]+prices[i])
// dp[i][3]: 第二次买入股票持有的最大现金, dp[i][3] = max(dp[i-1][3], dp[i-1][2]-prices[i])
// dp[i][4]: 第二次卖出股票持有的最大现金, dp[i][4] = max(dp[i-1][4], dp[i-1][3]+prices[i])
// 最大值一定是dp[i][4]
int maxFun(int p1, int p2)
{
return p1 > p2 ? p1 : p2;
}
int maxProfit(int* prices, int pricesSize) {
int dp[pricesSize][5];
// dp初始化
dp[0][0] = 0;
dp[0][1] = 0 - prices[0];
dp[0][2] = 0;
dp[0][3] = 0 - prices[0];
dp[0][4] = 0;
// 遍历
for (int i = 1; i < pricesSize; i++) {
dp[i][0] = 0;
dp[i][1] = maxFun(dp[i - 1][1], dp[i - 1][0] - prices[i]);
dp[i][2] = maxFun(dp[i - 1][2], dp[i - 1][1] + prices[i]);
dp[i][3] = maxFun(dp[i - 1][3], dp[i - 1][2] - prices[i]);
dp[i][4] = maxFun(dp[i - 1][4], dp[i - 1][3] + prices[i]);
}
return dp[pricesSize - 1][4];
}
今日收获
- 动态规划