【代码随想录】【算法训练营】【第46天】 [121]买卖股票的最佳时机 [122]买卖股票的最佳时机II [123]买卖股票的最佳时机III

前言

思路及算法思维,指路 代码随想录
题目来自 LeetCode

day 46,周六,坚持很困难~

题目详情

[121] 买卖股票的最佳时机

题目描述

121 买卖股票的最佳时机
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

题目描述

122 买卖股票的最佳时机II
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

题目描述

123 买卖股票的最佳时机III
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];
}

今日收获

  1. 动态规划
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值