买卖股票问题总结

24 篇文章 0 订阅

题目列表

解答

class Solution {
    public int maxProfit(int[] prices) {
        //dp[i][0]表示持有股票所得的最大金额
        //dp[i][1]表示不持有股票所得的最大金额
        int[][] dp = new int[prices.length][2];
        dp[0][0] = -prices[0];
        dp[0][1] = 0;
        for(int i = 1;i < prices.length;i++) {
            dp[i][0] = Math.max(dp[i - 1][0],-prices[i]);
            dp[i][1] = Math.max(dp[i - 1][1],prices[i] + dp[i - 1][0]);
        }
        return dp[prices.length - 1][1];
    }
}
class Solution {
    public int maxProfit(int[] prices) {
        int[] dp = new int[2];
        dp[0] = -prices[0];//dp[0]表示持有股票所得现金最大值
        dp[1] = 0;
        for(int i = 1;i <= prices.length;i++) {
            //前一天持有
            dp[0] = Math.max(dp[0],dp[1] - prices[i - 1]);
            //前一天卖出
            dp[1] = Math.max(dp[1],prices[i - 1] + dp[0]);
        }
        return dp[1];
    }
}
class Solution {
    public int maxProfit(int[] prices) {
        //每一天有五种状态,
        //0代表没有操作,1代表第一次买入,2代表第一次卖出,3代表第二次买入,4代表第二次卖出
        //dp数组的定义为第i天所处状态所得利润最大值
        int[][] dp = new int[prices.length][5];
        //dp初始化,dp[0][1] = -prices[0],dp[0][2] = 0,dp[0][3]第二次买入该初始化多少呢?
        //就相当于你在第一天买了又卖了,所以再买就是-prices[0],dp[0][4] = 0
        dp[0][1] = -prices[0];
        dp[0][3] = -prices[0];
        for(int i = 1;i < prices.length;i++) {
            dp[i][0] = dp[i - 1][0];
            dp[i][1] = Math.max(dp[i - 1][1],dp[i - 1][0] - prices[i]);
            dp[i][2] = Math.max(dp[i - 1][2],dp[i - 1][1] + prices[i]);
            dp[i][3] = Math.max(dp[i - 1][3],dp[i - 1][2] - prices[i]);
            dp[i][4] = Math.max(dp[i - 1][4],dp[i - 1][3] + prices[i]);
        }
        return dp[prices.length - 1][4];
    }
}
class Solution {
    public int maxProfit(int k, int[] prices) {
        //dp数组定义;第i天状态为j时,所得利润的最大值
        //j为0为不操作,1为第一次买入,2为第一次卖出...奇数买入,偶数卖出
        if(prices.length == 0) {
            return  0;
        }
        int[][] dp = new int[prices.length][2 * k + 1];
        for(int j = 1;j < 2 * k;j+=2) {
            dp[0][j] = -prices[0];
        }
        for(int i = 1;i < prices.length;i++) {
            for(int j = 0;j < 2 * k - 1;j+=2) {
                dp[i][j + 1] = Math.max(dp[i - 1][j + 1],dp[i - 1][j] - prices[i]);
                dp[i][j + 2] = Math.max(dp[i - 1][j + 2],dp[i - 1][j + 1] + prices[i]);
            }
        }
        return dp[prices.length - 1][2 * k];
    }
}
class Solution {
    public int maxProfit(int[] prices) {
        //dp有四种状态:
        //买入股票的状态:今天买入股票,或者昨天买入股票没有操作
        //卖出股票的状态:昨天已经是卖出状态,或者前天卖出,冷冻一天,今天卖出
        //冷冻状态,共四种状态
        int[][] dp = new int[prices.length][4];
        dp[0][0] = -prices[0];
        for(int i = 1;i < prices.length;i++) {
            dp[i][0] = Math.max(dp[i - 1][0],Math.max(dp[i - 1][3] - prices[i],dp[i - 1][1] - prices[i]));
            dp[i][1] = Math.max(dp[i - 1][1],dp[i - 1][3]);
            dp[i][2] = dp[i - 1][0] + prices[i];//达到今天卖出的状态,只能由昨天买入状态推导而来.
            dp[i][3] = dp[i - 1][2];
        }
        return Math.max(dp[prices.length - 1][3],Math.max(dp[prices.length - 1][2],dp[prices.length - 1][1]));
    }
}
class Solution {
    public int maxProfit(int[] prices, int fee) {
        int[][] dp = new int[prices.length][2];
        dp[0][0] = -prices[0];
        dp[0][1] = 0;
        for(int i = 1;i < prices.length;i++) {
            dp[i][0] = Math.max(dp[i - 1][0],dp[i - 1][1] - prices[i]);
            dp[i][1] = Math.max(dp[i - 1][1],dp[i - 1][0] + prices[i] - fee);
        }
        return dp[prices.length - 1][1];
    }
}

也可以用贪心

class Solution {
    public int maxProfit(int[] prices, int fee) {
        int n = prices.length;
        int profit = 0;
        int buy = prices[0] + fee;
        for(int i = 1;i < n;i++) {
            if(prices[i] + fee < buy) {
                buy = prices[i] + fee;
            }else if(prices[i] > buy) {
                profit += prices[i] - buy;
                buy = prices[i];
            }
        }
        return profit;
    }
}

总结

方法大差不差,有几道题只变了一点点,关键要明确状态的定义,进而写对递推方程.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值