动态规划解决股票问题

目录

121. 买卖股票的最佳时机 - 力扣(LeetCode)

122. 买卖股票的最佳时机 II - 力扣(LeetCode)

188. 买卖股票的最佳时机 IV - 力扣(LeetCode)

714. 买卖股票的最佳时机含手续费 - 力扣(LeetCode)


121. 买卖股票的最佳时机 - 力扣(LeetCode)

解析:

动态规划问题解决步骤可分为以下几点,可以帮我更好的理清逻辑

1.状态表示(根据题目要求  + 经验)

        本题要求我们只能交易一只股票,根据经验 我们可以这样表示:dp[i] = d[i - 1] + prices[ i ] 但是这样不行的,我们可以有两种状态 :买入 or 卖出 。我们可以画出这两种状态的转化图。

根据状态图,我们可以得到多状态表示

dp[ i ] [ 0 ] : 当前我手里没有股票,处于买入状态,此时我手中的钱。

dp[ i ] [ 1 ] :当前我手里有股票,处于卖出状态,此时我手里的钱。

2.状态转移方程

依据这个图        

dp [ i ] [ 0 ] =  max(dp[ i - 1] [ 0] , dp[i - 1] [ 1] + prices[ i - 1 ]);

dp[i ] [ 1] = max(dp[ i ] [ 1 ] , -prices[ i - 1 ]);

创建一个二维数组,0 / 1 表示当前我手中的股票状态:0代表我手里没有股票,1代表我有股票。

3.初始化

 本题需要加上一个虚拟节点,

第0天手上没有股票 :dp[ 0] [0]  = 0;         

第0天手上有股票:dp[0][1] = -prices[0]; 买了一只股票,手中余额为负数。

4.填表顺序

从左往右。

5.返回值: 返回dp数组中最大的元素.

6.编写代码:

class Solution {
    //动态规划:多状态dp
    public int maxProfit(int[] prices) {
        int n = prices.length;
        if(n == 1) return 0;
        int[][] dp = new int[n+1][2];
        dp[0][0] = 0;   dp[0][1] = -prices[0];
        int ret = Integer.MIN_VALUE;
        for(int i = 1; i <= n; i++){
            dp[i][0] = Math.max(dp[i-1][0],dp[i-1][1] + prices[i-1]);
            dp[i][1] = Math.max(dp[i-1][1], - prices[i-1]);
            ret = Math.max(dp[i][0],ret);
        }
        return Math.max(dp[n][0],dp[n][1]);
    }
}

122. 买卖股票的最佳时机 II - 力扣(LeetCode)

1.状态表示(根据题目要求  + 经验)

上来就定义:dp[i] : 表示第i天获得的最大利润。

dp[i] 等于前一天的利润加上当天的利润,但是当天的利润怎么求?应该等于当前价格 - 买入价格。但是发现定义的这个状态表示不能记录买入的价格。所以应该换一种思路,这样的状态表示是不合适的。

股票的状态有买入和卖出。可以定义两个状态表示。

2.状态转移方程

3.初始化

4.填表顺序

从左往右。

5.返回值: f数组 或者 g 数组的最大值

6.编写代码

class Solution {
    public int maxProfit(int[] prices) {
        int n = prices.length;
        int[] f = new int[n+1]; //处于买入状态的利润
        int[] g = new int[n+1]; //处于卖出状态的利润
        f[0] = -prices[0];
        int ret = 0;
        for(int i = 1; i <= n; i++){
            f[i]  = Math.max(f[i-1],g[i-1] - prices[i-1]);
            g[i] = Math.max(g[i-1],f[i-1] + prices[i-1]);
            ret  =  Math.max(ret , Math.max(f[i],g[i]));
        }
        return ret;
    }
}

188. 买卖股票的最佳时机 IV - 力扣(LeetCode)

1.状态表示

本题为多状态转移方程,定义状态表示

2.状态转移方程

3,代码

class Solution {
    public int maxProfit(int k, int[] prices) {
        int INT = 0x3f3f3f3f;
        int n = prices.length;
        k = Math.min( k, n / 2); //优化,k 大于 n 的情况
        int[][] f = new int[n+1][k+1];
        int[][] g = new int[n+1][k+1];
        for(int j = 0; j <= k; j++){
            f[0][j] = -INT;
            g[0][j] = -INT;
        }
        f[0][0] = -prices[0] ; g[0][0] = 0;
        for(int i = 1; i <= n; i++){
            for(int j = 0; j <= k; j++){
                f[i][j] = Math.max(f[i-1][j],g[i-1][j] - prices[i-1]);
                g[i][j] = g[i-1][j];
                if(j - 1 >= 0)
                g[i][j] = Math.max(g[i][j],f[i-1][j-1] + prices[i-1]);
            }
        }
        int ret = 0;
        for(int  j = 0; j <= k; j++){
            ret = Math.max(ret, g[n][j]);
        }
        return ret;
    }
}
714. 买卖股票的最佳时机含手续费 - 力扣(LeetCode)

1.状态表示

此题与  122题不差异,只不过在每次交易时多支付一次手续费。

2.状态转移方程

3.初始化

4.填表顺序

从左往右。

5.返回值: f数组 或者 g 数组的最大值

6.编写代码

class Solution {
    public int maxProfit(int[] p, int fee) {
        int n = p.length;
        int[] f = new int[n];
        int[] g = new int[n];
        f[0] = -p[0];
        for(int i = 1;i < n; i++){
            f[i] = Math.max(f[i-1],g[i-1] - p[i]);
            g[i] = Math.max(g[i-1],f[i-1] + p[i] - fee);
        }
        return Math.max(f[n-1],g[n-1]);
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值