Leetcode - Best Time to Buy and Sell Stock III

Paste_Image.png

My code:

public class Solution {
    public int maxProfit(int[] prices) {
        if (prices == null || prices.length == 0 || prices.length == 1)
            return 0;
        int[] left = new int[prices.length];
        int[] right = new int[prices.length];
        getMaxProfit(left, right, prices);
        int[] sum = new int[prices.length];
        int max = 0;
        for (int i = 0; i < prices.length; i++) {
            sum[i] = left[i] + right[i];
            if (max < sum[i])
                max = sum[i];
        }
        return max;
    }
    
    private void getMaxProfit(int[] left, int[] right, int[] prices) {
        int min = prices[0];  //represent the min prices
        int max = 0;  //represent the max profit
        for (int i = 1; i < prices.length; i++) {
            int temp = prices[i] - min;
            if (temp < 0) {
                left[i] = max;
                min = prices[i];
            }
            else if (temp <= max)
                left[i] = max;
            else {
                left[i] = temp;
                max = temp;
            }
        }
        
        int rightMax = prices[prices.length - 1];
        int profitMax = 0;
        for (int i = prices.length - 2; i >= 0; i--) {
            int temp = rightMax - prices[i];
            if (temp < 0) {
                right[i] = profitMax;
                rightMax = prices[i];
            }
            else if (temp < profitMax)
                right[i] = profitMax;
            else {
                right[i] = temp;
                profitMax = temp;
            }   
        }
    }
}

My test result:

Paste_Image.png

这次作业没能有自己的思路,然后看了一篇博客,写的很好,思路很明确清晰,于是我按照这个思路自己写了出来。
顺便把这个系列的题目总结下吧。
第一题,就是给你一串数,然后买进卖出,最多只做一次交易,求最大利润。
那么,其实就是,DP,从 i = 1开始,不断地向前递进,每一次,
计算下prices[i] - min 的值,
如果大于max,那就设这个值为max,
如果小于max但>=0,则保持max, min不变。
如果小于0,则更新min为当前值。
所以说,max代表的是当前范围内的最大利润,而min表示当前范围内的最大利润中,买进的价格。不一定是当前范围内的最小值。
然后遍历一遍即可以得出结果。

第二题,同样是一串数,买进卖出。但是,允许无限次交易,求最大利润。
因为允许无限次交易。可以设置一个数组diff[],用来记录前后两个数的差值,
如果大于0,则全部累加到变量max上。
如果小于0,就不加。
遍历结束后,该max即为最大利润。
为什么?
比如,2, 3, 5, 7
如果是递增数列,那么
7 - 2 = (3- 2) + (5- 3) + (7 - 5)
如果出现递减的,比如,2, 1, 5, 3, 7
这里就有一个注意点,如果是无限次交易,那我就是买进1,卖出5,然后买进3卖出7,这样赚的最多,所以可以累加。可以把每一次出现的递减点,当做是新的一次交易的买进值。
但是,如果限制只允许一次交易,那么就该是,买进1,卖出7。即需要采用第一题的思路了。

第三题,同样是一串数,买进卖出,但是,只允许最多两次交易,求最大利润。
所以,可以把数组一切为2,[0, i] 为第一次交易, [i, prices.length - 1] 为第二次交易。
特定到i点时,可在i点把货物卖出,作为[0, i]区域的终结,然后再i点把货物买入, 作为[i, prices.length - 1]区域的开始,

于是可以设置两个数组,left[], right[]
left[i] 表示 [0, i] 这么一段区域内,交易一次最大的利润。可以用第一题的算法来解决。
right[i] 表示 [i, prices.length - 1] 这么一段区域内,交易一次最大的利润,可以反过来用第一题的思路来解决。
left[i] + right[i] 即等于在第i天时为分界点进行两次交易的最大利润值。
然后遍历获得这些分界点利润最大值中的最大值,即为我们需要的最大利润。
我觉得文章里有句话说的挺对的,
看来以后碰到与2相关的问题,一定要想想能不能用二分法来做!

Paste_Image.png

http://blog.csdn.net/fightforyourdream/article/details/14503469

第四题,等等更新。
放弃吧。。。。感觉好他妈复杂。具体做法有时间还是看上面那个网页对应的文章。
最后还是测试过了,但主要还是拷贝了代码,这道题目真的很难啊。。。逻辑复杂,代码简单。需要考虑的一个情况是,
当 k >= prices.length, 的时候,就直接用
Best Time to Buy and Sell Stock II 的无限次交易方法来做,测试就过了。http://www.cnblogs.com/grandyang/p/4295761.html

**
总结:DP 以后碰到与2相关的问题,一定要想想能不能用二分法来做!
老爸好像吃坏肚子了,然后拉肚子之后还发烧,感觉爸妈的身体真的没以前好了,如果我不在家,他们。。。不能去想了。要想走出去,必须得有牺牲。
我们不是贵族阶级。
**

Anyway, Good luck, Richardo!


public class Solution {
    public int maxProfit(int[] prices) {
        if (prices == null || prices.length == 0 || prices.length == 1)
            return 0;
        int[] profits = new int[prices.length];
        int[] left = new int[prices.length];
        int[] right = new int[prices.length];
        
        process(prices, left, right);
        for (int i = 0; i < profits.length; i++)
            profits[i] = left[i] + right[i];
        Arrays.sort(profits);
        return profits[profits.length - 1];
    }
    
    private void process(int[] prices, int[] left, int[] right) {
        left[0] = 0;
        right[right.length - 1] = 0;
        
        int min = prices[0];
        for (int i = 1; i < left.length; i++) {
            left[i] = Math.max(left[i - 1], prices[i] - min);
            min = Math.min(min, prices[i]);
        }
        
        int max = prices[prices.length - 1];
        for (int i = right.length - 2; i >= 0; i--) {
            right[i] = Math.max(right[i + 1], max - prices[i]);
            max = Math.max(max, prices[i]);
        }
    }
}
      ---- 09/23/2015 23:17

Anyway, Good luck, Richardo!


My code:

public class Solution {
    public int maxProfit(int[] prices) {
        if (prices == null || prices.length <= 1)
            return 0;
        int max = 0;
        int[] profits = new int[prices.length];
        int buy = prices[0];
        /** 1: [0, i];   2: [i + 1, prices.length - 1] 
         * scan for transaction 1, [0, i], i++
         */
        for (int i = 1; i < prices.length; i++) {
            if (prices[i] >= buy) {
                max = Math.max(max, prices[i] - buy);
            }
            else {
                buy = prices[i];                
            }
            profits[i] = max;
        }
        
        /** scan for tracnsaction 2, [i + 1, prices.length - 1], i-- */
        int sell = prices[prices.length - 1];
        max = 0;
        for (int i = prices.length - 2; i >= 0; i--) {
            if (prices[i + 1] <= sell) {
                max = Math.max(max, sell - prices[i + 1]);
            }
            else {
                sell = prices[i + 1];
            }
            profits[i] += max;
        }
        Arrays.sort(profits);
        
        return profits[profits.length - 1];
    }
}

一开始做的超时了。因为有许多重复操作。
然后改了下。做了出来,没看答案。虽然原来的做法还有些印象。

Anyway, Good luck, Richardo!

差不多的思路。
今天找人投了 amazon, ea, 还有校招的 two sigma
全职之战开始了。
好运。

Anyway, Good luck, Richardo! -- 08/19/2016

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,362评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,330评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,247评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,560评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,580评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,569评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,929评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,587评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,840评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,596评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,678评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,366评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,945评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,929评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,165评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,271评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,403评论 2 342

推荐阅读更多精彩内容