Leetcode 188. Best Time to Buy and Sell Stock IV

問題描述

Say you have an array for which the ith element is the price of a given stock on day i.

Design an algorithm to find the maximum profit. You may complete at most k transactions.

Note:
You may not engage in multiple transactions at the same time (ie, you must sell the stock before you buy again).

Credits:
Special thanks to @Freezen for adding this problem and creating all test cases.

問題分析:
該問題就是在股票買賣問題的基礎之上加上最大交易次數k的限制條件,實際上變成了0-1揹包問題。選擇2*k個數,使得效益最大,但是對於不同的數存在不同的計算方式。
解題思路:

 問題的實質是從長度爲n的prices數組中挑選出至多2*k個元素,組成一個交易序列。
交易序列中的首次交易爲買入,其後賣出和買入操作交替進行。
總收益爲交易序列中的偶數項之和 - 奇數項之和。

dp[j]表示完成j次交易時最大收益,轉移方程:
dp[j]=max(dp[j],dp[j-1]+(j%2==0?1:-1)*prices[i])

當j爲奇數時,交易類型爲買入;當j爲偶數時,交易類型爲賣出。

注意:當n<2*k時,直接計算最大收益即可。
代碼如下:

    public int maxProfit(int k, int[] prices) {
        int n=prices.length;
        if(n<=k*2)
            return getProfit(prices);
        int[]dp=new int[2*k+1];
        for(int i=1;i<=2*k;i++)
            dp[i]=Integer.MIN_VALUE;
        for(int i=0;i<n;i++){
            for(int j=1;j<=2*k;j++){
                dp[j]=Math.max(dp[j],dp[j-1]+(j%2==0?1:-1)*prices[i]);
            }
        }
        return dp[2*k];
    }
    public int getProfit(int[] prices){
        int sum=0;
        for(int i=0;i<prices.length-1;i++){
            if(prices[i+1]-prices[i]>0)
                sum+=prices[i+1]-prices[i];
        }
        return sum;
    }

其實如果利用之前沒有限制交易次數問題的解法同樣有:(注意,sell[j]=max(sell[j],buy[j]+prices[i])

    public int maxProfit(int k, int[] prices) {
        if (k < 1 || prices == null || prices.length < 2) return 0;
        if (k >= prices.length/2) {
            int max = 0;
            for(int i=1; i<prices.length; i++) max += Math.max(0, prices[i]-prices[i-1]);
            return max;
        }
        int[] buy = new int[k];
        int[] sell = new int[k];
        Arrays.fill(buy, Integer.MIN_VALUE);
        for(int i=0; i<prices.length; i++) {
            for(int j=0; j<k; j++) {
                buy[j] = Math.max(buy[j], j==0?-prices[i]:sell[j-1]-prices[i]);
                sell[j] = Math.max(sell[j], buy[j]+prices[i]);
            }
        }
        return sell[k-1];
    }

參考鏈接:
http://bookshadow.com/weblog/2015/02/18/leetcode-best-time-to-buy-and-sell-stock-iv/
http://lib.csdn.net/article/datastructure/21116

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章