题解 | #股票交易日#

股票交易日

https://www.nowcoder.com/practice/3e8c66829a7949d887334edaa5952c28

import java.util.*;

public class Stock {
    public int maxProfit(int[] prices, int n) {
        // return solution1(prices, n);
        // return solution2(prices, n);
        return solution3(prices, n);
    }

    /**
     * 动态规划: 状态机
     *
     * 两次交易同时开始
     *
     * dp[i][0]表示股票前i种价格第一次交易买入后所得收益
     * dp[i][1]表示股票前i种价格第一次交易卖出后所得收益
     * dp[i][2]表示股票前i种价格第二次交易买入后所得收益
     * dp[i][3]表示股票前i种价格第二次交易卖出后所得收益
     *
     * 四种状态:
     * 第一次交易买入: 要么是之前买的, 要么是今天买的
     * 第一次交易卖出: 要么是之前卖的, 要么是今天卖的
     * 第二次交易买入: 要么是之前买的, 要么是今天买的
     * 第二次交易卖出: 要么是之前卖的, 要么是今天卖的
     *
     * 分别对应关系式:
     * dp[i][0] = max(dp[i-1][0], -prices[i])
     * dp[i][1] = max(dp[i-1][1], dp[i-1][0]+prices[i])
     * dp[i][2] = max(dp[i-1][2], dp[i-1][1]-prices[i])
     * dp[i][3] = max(dp[i-1][3], dp[i-1][2]+prices[i])
     *
     * @param prices
     * @param n
     * @return
     */
    private int solution1(int[] prices, int n){
        int[][] dp = new int[n][4];

        // 一次买入
        dp[0][0] = -prices[0];
        // 一次卖出
        dp[0][1] = 0;
        // 二次买入
        dp[0][2] = -prices[0];
        // 二次卖出
        dp[0][3] = 0;
        for(int i=1; i<n; i++){
            dp[i][0] = Math.max(dp[i-1][0], -prices[i]);
            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]);
        }

        return dp[n-1][3];
    }

    /**
     * 动态规划: 状态机
     *
     * 两次交易同时开始
     *
     * buy1 表示股票前i种价格第一次交易买入后所得收益
     * sell1 表示股票前i种价格第一次交易卖出后所得收益
     * buy2 表示股票前i种价格第二次交易买入后所得收益
     * sell2 表示股票前i种价格第二次交易卖出后所得收益
     *
     * 四种状态:
     * 第一次交易买入: 要么是之前买的, 要么是今天买的
     * 第一次交易卖出: 要么是之前卖的, 要么是今天卖的
     * 第二次交易买入: 要么是之前买的, 要么是今天买的
     * 第二次交易卖出: 要么是之前卖的, 要么是今天卖的
     *
     * 分别对应关系式:
     * buy1 = max(buy1, -prices[i])
     * sell1 = max(sell1, buy1+prices[i])
     * buy2 = max(buy2, sell1-prices[i])
     * sell2 = max(sell2, buy2+prices[i])
     *
     * @param prices
     * @param n
     * @return
     */
    private int solution2(int[] prices, int n){
        // 一次买入
        int buy1 = -prices[0];
        // 一次卖出
        int sell1 = 0;
        // 二次买入
        int buy2 = -prices[0];
        // 二次卖出
        int sell2 = 0;
        for(int i=1; i<n; i++){
            buy1 = Math.max(buy1, -prices[i]);
            sell1 = Math.max(sell1, buy1+prices[i]);
            buy2 = Math.max(buy2, sell1-prices[i]);
            sell2 = Math.max(sell2, buy2+prices[i]);
        }

        return sell2;
    }

    /**
     * 动态规划: 双向
     * @param prices
     * @param n
     * @return
     */
    private int solution3(int[] prices, int n){
        int[] left = new int[n];
        int[] right = new int[n];
        int leftMin = prices[0];
        int rightMax = prices[n-1];
        int sum = 0;
        
        // 左段一次交易最大收益
        for(int i=1; i<n; i++){
            leftMin = Math.min(prices[i], leftMin);
            left[i] = Math.max(prices[i]-leftMin, left[i-1]);
        }
        // 右段一次交易最大收益
        for(int i=n-2 ; i>=0; i--){
            rightMax = Math.max(prices[i], rightMax);
            right[i] = Math.max(rightMax-prices[i], right[i+1]);
        }
        // 两次交易最大收益
        for(int i=0 ; i<n; i++){
            sum = Math.max(sum, left[i]+right[i]);
        }

        return sum;
    }
}

全部评论

相关推荐

不愿透露姓名的神秘牛友
07-07 18:05
哈哈哈哈哈感觉朋友找工作的已经疯掉了,直接上图
码农索隆:真老板娘:“我嘞个去,这不我当年的套路吗
点赞 评论 收藏
分享
程序员小白条:你是沟通了900个,不是投了900份简历,你能投900份,意味着对面都要回复你900次,你早就找到实习了,没亮点就是这样的,别局限地区,时间投的也要早,现在都要7月了
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务