zoukankan      html  css  js  c++  java
  • Best Time to Buy and Sell Stock III

    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 two transactions.

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

    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 two transactions. 
    设计一个算法来计算最大收益。你至多可以完成两次交易。

    这个题可以借鉴第一个题目Best Time to Buy and Sell Stock中的思路。这个题是一个动态规划的题目。我们假设将1-n天分为1-day,day-n两部分,然后我们分别在两部分中至多进行一次交易获得两部分的最大值,将两部分加在一起就是一个待选的最大收益,day可以取1,2,…,n,所以会得到n个后选值,在候选值中选出最大的一个就是最大收益。借鉴Best Time to Buy and Sell Stock中计算最大收益的方法,我们将1-day的最大收益放进left[day]中,将day-n的最大收益放进right[day]中,day=1,..n。再求两部分和的最大值。

    class Solution {
        /**因为下次购买必须在上一次的卖掉以后才行。所以
        我们将1-n天分成1..day,day...n两部分,day=1,2,...n。然后在两部分中分别最多进行一次交易,然后求两个的和的最大值(不同的day)。
        我们将1-day的最大收益放进left[day]中,将day-n的最大收益放进right[day]中,day=1,..n。再求两部分和的最大值。
        
        */
        public int maxProfit(int[] prices) {
            
            if(prices==null||prices.length<2) return 0;
            //用两个数组,一个表示1-day的不同day最大收益,一个表示day-n的最大收益
            int[] left=new int[prices.length];
            int[] right=new int[prices.length];
            
            //先求left[day],也就是前部分1-day的最大收益,找出day前面的最小值
            int min=prices[0];
            left[0]=0;
            for(int day=1;day<prices.length;day++){
                min=Math.min(min,prices[day]);
                left[day]=Math.max(left[day-1],prices[day]-min);//当前位置最大利益,要么就是前面一个位置的最大利益,要么就是当前位置-前面最小值
            }
            
            //再求right[n].从后往前求,因为前面的区间是变的
            int max=prices[prices.length-1];
            right[prices.length-1]=0;  //因为right[prices.length-1]表示prices.length-1到prices.length-1,是0
            for(int day=prices.length-2;day>=0;day--){
                max=Math.max(max,prices[day]);
                right[day]=Math.max(right[day+1],max-prices[day]);
            }
            
            //求最大利益
            int maxPro=0;
            for(int day=0;day<prices.length;day++){
                maxPro=Math.max(maxPro,left[day]+right[day]);
            }
            
            return maxPro;
            
        }
    }

    解法二

    在Discuss中看到一种很棒的解法,代码只有10行左右,但是不是很好理解。

    第二种解法的核心是假设手上最开始只有0元钱,那么如果买入股票的价格为price,手上的钱需要减去这个price,如果卖出股票的价格为price,手上的钱需要加上这个price。

    它定义了4个状态:

    Buy1[i]表示前i天做第一笔交易买入股票后剩下的最多的钱;

    Sell1[i]表示前i天做第一笔交易卖出股票后剩下的最多的钱;

    Buy2[i]表示前i天做第二笔交易买入股票后剩下的最多的钱;

    Sell2[i]表示前i天做第二笔交易卖出股票后剩下的最多的钱;

    那么Sell2[i]=max{Sell2[i-1],Buy2[i-1]+prices[i]}

           Buy2[i]=max{Buy2[i-1],Sell[i-1]-prices[i]}

           Sell1[i]=max{Sell[i-1],Buy1[i-1]+prices[i]}

           Buy1[i]=max{Buy[i-1],-prices[i]}

    可以发现上面四个状态都是只与前一个状态有关,所以可以不使用数组而是使用变量来存储即可。

    public int maxProfit(int[] prices) {
            int hold1 = Integer.MIN_VALUE, hold2 = Integer.MIN_VALUE;
            int release1 = 0, release2 = 0;
            for(int i:prices){                              // Assume we only have 0 money at first
                release2 = Math.max(release2, hold2+i);     // The maximum if we've just sold 2nd stock so far.
                hold2    = Math.max(hold2,    release1-i);  // The maximum if we've just buy  2nd stock so far.
                release1 = Math.max(release1, hold1+i);     // The maximum if we've just sold 1nd stock so far.
                hold1    = Math.max(hold1,    -i);          // The maximum if we've just buy  1st stock so far. 
            }
            return release2; ///Since release1 is initiated as 0, so release2 will always higher than release1.
        }
  • 相关阅读:
    HDU 1828 Picture
    HDU 2656 Counting Game
    HDU 3265 Posters
    Android颜色选择器之案例解析
    实现半透明的popupwindow的源码
    用activity实现半透明的、淡入的menu【原创】
    Android webservice的用法详细讲解
    Android Fragments 详细使用详细介绍
    在Android中扫描wifi热点演示实例教程
    用Dialog创建带箭头的对话框
  • 原文地址:https://www.cnblogs.com/xiaolovewei/p/8330454.html
Copyright © 2011-2022 走看看