题解 | #牛群买卖计划II#

牛群买卖计划II

https://www.nowcoder.com/practice/3fa6bc9c3a724b4089eea26d3f87171b?tpId=354&tqId=10595792&ru=/exam/oj&qru=/ta/interview-202-top/question-ranking&sourceUrl=%2Fexam%2Foj%3Fpage%3D1%26tab%3D%25E7%25AE%2597%25E6%25B3%2595%25E7%25AF%2587%26topicId%3D354

动态规划

在每两天之间购入和卖出,并取最大利润,买入前必须卖出

0 <= k <= 100 //交易次数(一次买入卖出)

0 <= prices.length <= 10000 //可供交易的天数

0 <= prices[i] <= 2000 //价格区间

prices.lenght=n天一共可交易n/2次

//故当k>n/2时可以认为,每当相邻的两天可获利时,必然进行了一次买入卖出,此时利润最大

记录每一次买卖后的利润,并挑选最大值记录

可以将利润数组分为买入和卖出数组,计算每一次买入后最大剩余金额(包含之前的利润)+卖出后的金额=利润

则计算sell数组中的最大值即为最大利润(有部分情形下,一次买卖即可达到最大利润)

    public static int maxProfitII(int[] prices, int k) {
        int n = prices.length;
        //当交易次数>一半时,可以认为每天都至少进行了一次买入或卖出操作
        if (k > n / 2) {
            int ans = 0;
            for (int i = 1; i < n; i++) {
                ans += Math.max(0, prices[i] - prices[i - 1]);
            }
            return ans;
        }
        //定义买入后剩余,卖出后利润数组
        int[][] buy = new int[n][k + 1];
        int[][] sell = new int[n][k + 1];
        //第一天购入
        buy[0][0] = -prices[0];
        //卖出
        sell[0][0] = 0;
        //初始化购买后剩余,由于购买后必须卖出才能再次购买
        for (int i = 1; i <= k; i++) {
            buy[0][i] = sell[0][i] = -2001;//,故卖出后最小剩余为0-2000,取余量再-1
        }
        for (int i = 1; i < n; ++i) {
            //在昨天购买或今天购买后取最大剩余
            buy[i][0] = Math.max(buy[i - 1][0], sell[i - 1][0] - prices[i]);
            for (int j = 1; j <= k; ++j) {// 一共卖出k次,假设是第j次卖出
                // 在昨天卖出或今天卖出取最大剩余
                buy[i][j] = Math.max(buy[i - 1][j], sell[i - 1][j] - prices[i]);
                // 在昨天卖出后利润与今天卖出后利润取最大利润
                sell[i][j] = Math.max(sell[i - 1][j], buy[i - 1][j - 1] + prices[i]);
            }
        }

        return Arrays.stream(sell[n-1]).max().getAsInt();;
    }

面试高频TOP202 文章被收录于专栏

面试高频TOP202题解

全部评论

相关推荐

点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务