成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

[Leetcode] Best Time to Buy and Sell Stock 買賣股票的最佳

nanchen2251 / 538人閱讀

摘要:雙指針?lè)◤?fù)雜度時(shí)間空間思路根據(jù)買賣股票的特性,我們必須先低價(jià)買,再高價(jià)賣,這個(gè)找最大收益的過(guò)程實(shí)際上是找到目前為之的最低價(jià)。我們可以利用這個(gè)之前計(jì)算的結(jié)果降低時(shí)間復(fù)雜度不過(guò)代價(jià)是額外空間,所以需要把到的最大收益存在數(shù)組中。

Best Time to Buy and Sell Stock I

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

If you were only permitted to complete at most one transaction (ie, buy one and sell one share of the stock), design an algorithm to find the maximum profit.

雙指針?lè)?/b> 復(fù)雜度

時(shí)間 O(N) 空間 O(1)

思路

根據(jù)買賣股票的特性,我們必須先低價(jià)買,再高價(jià)賣,這個(gè)找最大收益的過(guò)程實(shí)際上是找到目前為之的最低價(jià)。在遍歷價(jià)格數(shù)組時(shí),根據(jù)這個(gè)動(dòng)態(tài)更新的最低價(jià)和當(dāng)前的價(jià)格可以算出當(dāng)前賣股票最大能賺多少錢。

代碼
public class Solution {
    public int maxProfit(int[] prices) {
        int min = Integer.MAX_VALUE, res = 0;
        for(int i = 0 ; i < prices.length; i++){
            if(prices[i]res) res = prices[i] - min;
        }
        return res;
    }
}
Best Time to Buy and Sell Stock II

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 as many transactions as you like (ie, buy one and sell one share of the stock multiple times). However, you may not engage in multiple transactions at the same time (ie, you must sell the stock before you buy again).

貪心法 復(fù)雜度

時(shí)間 O(N) 空間 O(1)

思路

既然能買賣任意次,那最大收益的方法就是盡可能多的低入高拋。只要明天比今天價(jià)格高,就應(yīng)該今天買入明天再賣出。

代碼
public class Solution {
    public int maxProfit(int[] prices) {
        int sum = 0;
        for(int i = 1; i < prices.length; i++){
            if(prices[i]>prices[i-1]) sum += prices[i] - prices[i-1];
        }
        return sum;
    }
}
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).

雙向動(dòng)態(tài)規(guī)劃 復(fù)雜度

時(shí)間 O(N) 空間 O(N)

思路

最簡(jiǎn)單的方法就是對(duì)每一個(gè)時(shí)間點(diǎn),將其所有兩邊的數(shù)組都執(zhí)行一次Best Time to Buy and Sell Stock I的解法,但這會(huì)帶來(lái)O(N^2)的時(shí)間復(fù)雜度。實(shí)際上當(dāng)計(jì)算prices[0]到prices[i]的最大收益時(shí),我們已經(jīng)計(jì)算過(guò)prices[0]到prices[i-1]的最大收益了,prices[0]到prices[i]的最大收益應(yīng)該是當(dāng)前賣出能獲得的最大收益和prices[0]到prices[i-1]的最大收益中,二者較大的那個(gè)。我們可以利用這個(gè)之前計(jì)算的結(jié)果降低時(shí)間復(fù)雜度(不過(guò)代價(jià)是額外空間),所以需要把prices[0]到prices[i]的最大收益存在left[i]數(shù)組中。具體解法和I是一樣的,也是維護(hù)一個(gè)前半段最小值。

分別得出以i點(diǎn)為分割點(diǎn),左半段最大收益的數(shù)組left,和右半段最大收益的數(shù)組right后,我們就可以遍歷一遍這兩個(gè)數(shù)組,找出最大的left+right組合。實(shí)際上,該解法就是將I的解法雙向各執(zhí)行一遍并記錄結(jié)果。

代碼
public class Solution {
    public int maxProfit(int[] prices) {
        if(prices.length == 0) return 0;
        int[] left = new int[prices.length];
        int[] right = new int[prices.length];
        int leftMin = prices[0];
        int rightMax = prices[prices.length-1];
        int sum = 0;
        //計(jì)算左半段最大收益
        for(int i = 1 ; i < prices.length; i++){
            leftMin = Math.min(prices[i], leftMin);
            left[i] = Math.max(prices[i] - leftMin, left[i-1]);
        }
        //計(jì)算右半段最大收益
        for(int i = prices.length - 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 < prices.length; i++){
            if((left[i]+right[i])>sum) sum = left[i]+right[i];
        }
        return sum;
    }
}
滾動(dòng)掃描法 復(fù)雜度

時(shí)間 O(N) 空間 O(1)

思路

其實(shí)我們并不需要知道每個(gè)時(shí)間點(diǎn)買賣第一第二筆股票收益的全部信息,我們只要知道前一個(gè)時(shí)間點(diǎn)買賣第一第二筆股票的最大收益信息,就可以直到當(dāng)前最大的收益信息了,這樣可以為我們省去額外空間。這里我們遍歷prices數(shù)組的時(shí)候,維護(hù)四個(gè)變量:release2是在該價(jià)格點(diǎn)賣出第二筆股票后手里剩的錢,等于上一輪買入第二筆股票后手里剩的錢加上賣出當(dāng)前股票價(jià)格的錢,或者上一輪賣出第二筆股票后手里剩的錢兩者中較大的。hold2是在該價(jià)格點(diǎn)買入第二筆股票后手里剩的錢,等于上一輪賣出第一筆股票后手里剩的錢減去買入當(dāng)前股票價(jià)格的錢,或者上一輪買入第二筆股票后手里剩的錢兩者中較大的。release1是在該價(jià)格點(diǎn)賣出第一筆股票后手里剩的錢,等于上一輪買入第一筆股票后手里剩的錢加上賣出當(dāng)前股票價(jià)格的錢,或者上一輪賣出第一筆股票后手里剩的錢兩者中較大的。hold1是在該價(jià)格點(diǎn)買入第一筆股票后手里剩的錢,等于初始資金減去買入當(dāng)前股票價(jià)格的錢或者初始資金(不買)中較大的。這里計(jì)算順序按照release2 -> hold2 -> release1 -> hold1,因?yàn)橘u是要后于買的,而第二次交易也是后于第一次交易的,通過(guò)這個(gè)順序我們能用這些變量自身來(lái)記錄上次的值。相當(dāng)于release2的時(shí)間點(diǎn)要先于hold1四個(gè)點(diǎn)。

Prices      3    1    2    8    3    1    9    6
release2    0    0    1    7    7    7    1    1
hold2      -3   -1   -1   -1    4    6    1    1
release1    0    0    1    7    7    7    1    1
hold1      -3   -1   -1   -1   -1   -1    3    3
代碼
public class Solution {
    public int maxProfit(int[] prices) {
        int hold1 = Integer.MIN_VALUE, hold2 = Integer.MIN_VALUE;
        int release1 = 0, release2 = 0;
        for(int i = 0; i < prices.length; i++){
            //在該價(jià)格點(diǎn)賣出第二筆股票后手里剩的錢,等于上一輪買入第二筆股票后手里剩的錢加上賣出當(dāng)前股票價(jià)格的錢,或者上一輪賣出第二筆股票后手里剩的錢兩者中較大的
            release2 = Math.max(release2, hold2 + prices[i]);
            //在該價(jià)格點(diǎn)買入第二筆股票后手里剩的錢,等于上一輪賣出第一筆股票后手里剩的錢減去買入當(dāng)前股票價(jià)格的錢,或者上一輪買入第二筆股票后手里剩的錢兩者中較大的
            hold2 = Math.max(hold2, release1 - prices[i]);
            //在該價(jià)格點(diǎn)賣出第一筆股票后手里剩的錢,等于上一輪買入第一筆股票后手里剩的錢加上賣出當(dāng)前股票價(jià)格的錢,或者上一輪賣出第一筆股票后手里剩的錢兩者中較大的
            release1 = Math.max(release1, hold1 + prices[i]);
            //在該價(jià)格點(diǎn)買入第一筆股票后手里剩的錢,等于初始資金減去買入當(dāng)前股票價(jià)格的錢或者初始資金(不買)中較大的
            hold1 = Math.max(hold1, -prices[i]);
        }
        return release2;
    }
}
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).

動(dòng)態(tài)規(guī)劃 復(fù)雜度

時(shí)間 O(Nk) 空間 O(Nk)

思路

我們將第i天已經(jīng)執(zhí)行j筆交易的最大收益作為全局變量global,將第i天正好完成第j筆交易的最大收益作為局部變量local。

對(duì)于global,也就是我們要知道第i天已經(jīng)執(zhí)行j筆交易的最大收益,可以基于第i-1天已經(jīng)執(zhí)行j筆交易的最大收益和第i天正好完成第j筆交易的最大收益,即globali = max(globali-1, locali)。

對(duì)于local,也就是我們要知道第i天正好完成第j筆交易的最大收益,可以基于第i-1天正好完成第j-1筆交易的最大收益加上當(dāng)天交易的差值,還有第i-1天正好完成第j筆交易的最大收益加上當(dāng)天交易的差值。要注意的是,第i-1天正好完成第j-1筆交易這種情況,當(dāng)前交易的差值取0和實(shí)際昨天今天差價(jià)中較大的,因?yàn)槲覀冞€有一次自由交易的余地,所以如果虧的話完全可以當(dāng)天買賣避免損失。但第i-1天正好完成第j筆交易這種情況來(lái)推導(dǎo)第i天正好完成第j筆交易時(shí),相當(dāng)于第i天已經(jīng)要連著第i-1天交易,使得第i-1天正好完成的第j筆交易和第i天正好完成的第j筆交易是同一個(gè)交易。算式是:locali = max(locali-1+max(0, diff), locali-1+diff)

注意

對(duì)于k > prices.length / 2的情況,我們可以用II的解法來(lái)節(jié)省空間。因?yàn)榘凑疹}意必須先買后賣,那么對(duì)于n天交易,能夠產(chǎn)生有效收益的交易次數(shù)是小于等于n/2的,只有不同天買賣才能產(chǎn)生差價(jià)。對(duì)于大于n/2的那部分交易,必定是當(dāng)天買賣沒(méi)有任何收益的,無(wú)論交易多少次都是一樣的。所以如果k > prices.length / 2,就相當(dāng)于無(wú)限次交易。

數(shù)組的第二維初始化長(zhǎng)度是k+1,因?yàn)槲覀円A(yù)留完成0筆交易的收益,是0。

代碼
public class Solution {
    public int maxProfit(int k, int[] prices) {
        if(prices.length == 0) return 0;
        //用II的解法優(yōu)化k > prices.length / 2的情況
        if(k > prices.length / 2){
            int sum = 0;
            for(int i = 1; i < prices.length; i++){
                if(prices[i]>prices[i-1]) sum += prices[i] - prices[i-1];
            }
            return sum;
        }
        //初始化全局變量和局部變量
        int[][] global = new int[prices.length][k+1];
        int[][] local = new int[prices.length][k+1];
        for(int i = 1; i < prices.length; i++){
            int diff = prices[i] - prices[i-1];
            for(int j = 1; j < k + 1; j++){
                //更新局部變量
                local[i][j] = Math.max(global[i-1][j-1]+Math.max(0, diff), local[i-1][j]+diff);
                //更新全局變量
                global[i][j] = Math.max(global[i-1][j], local[i][j]);
            }
        }
        return global[prices.length - 1][k];
    }
}
滾動(dòng)掃描法 復(fù)雜度

時(shí)間 O(N) 空間 O(k)

思路

這個(gè)解法和III中滾動(dòng)掃描法是一樣的,區(qū)別在于III我們用了固定的四個(gè)變量來(lái)記錄兩次交易,而IV中我們需要2k個(gè)變量來(lái)記錄k次交易。

注意

數(shù)組長(zhǎng)度要初始為k+1,這樣方便我們處理第一筆交易的情況。

代碼
public class Solution {
    public int maxProfit(int k, int[] prices) {
        //用II的解法優(yōu)化k > prices.length / 2的情況
        if(k > prices.length / 2){
            int sum = 0;
            for(int i = 1; i < prices.length; i++){
                if(prices[i]>prices[i-1]) sum += prices[i] - prices[i-1];
            }
            return sum;
        }
        //初始化買賣股票后剩余金錢的數(shù)組
        int[] release = new int[k+1];
        int[] hold = new int[k+1];
        for(int i = 0; i < k+1; i++){
            hold[i]=Integer.MIN_VALUE;
        }
        for(int i = 0; i < prices.length; i++){
            for(int j = 1; j < k+1; j++){
                //賣出第j筆交易,所剩余的錢
                release[j] = Math.max(release[j], hold[j]+prices[i]);
                //買入第j筆交易,所剩余的錢
                hold[j] = Math.max(hold[j], release[j-1]-prices[i]);
            }
        }
        return release[k];
    }
}
后續(xù) Follow Up

Q:如果對(duì)于每個(gè)時(shí)間點(diǎn),都可以買入1次,而對(duì)于每個(gè)時(shí)間點(diǎn),都可以賣出之前持有的任意多個(gè)股票,該如何計(jì)算?
A:因?yàn)榭梢猿掷m(xù)持有多個(gè)之前買的股票,我們可以一直買入并持有,直到第一個(gè)全局最高點(diǎn)時(shí)再一起賣出去。接著我們?cè)僖恢辟I入,直到剩余價(jià)格中的全局最高點(diǎn)時(shí)賣出去,以此類推。這里提供兩個(gè)解題思路:

先遍歷一遍找出所有峰值,并將這些峰值和他們的坐標(biāo)打包起來(lái),扔進(jìn)一個(gè)Heap。這樣再?gòu)念^遍歷一遍,先拿出堆頂,把直到堆頂坐標(biāo)之前的差值都累加起來(lái),過(guò)了這個(gè)堆頂?shù)淖鴺?biāo)后再看下一個(gè)有效堆頂(有效堆頂是指下標(biāo)在當(dāng)前下標(biāo)之后的)。時(shí)間復(fù)雜度O(NlogN)。

先找出全局最高點(diǎn),然后在整個(gè)數(shù)組之前加一個(gè)最大值元素,這樣就把這道題轉(zhuǎn)換成了積水問(wèn)題。時(shí)間復(fù)雜度O(N)。

Q: 如果每次交易有手續(xù)費(fèi)怎么辦?
A: 手續(xù)費(fèi)實(shí)際上就是降低了賣價(jià)(或者等同于提高了買價(jià)),我們根據(jù)手續(xù)費(fèi)相應(yīng)調(diào)整利潤(rùn)就行了。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/66162.html

相關(guān)文章

  • Best Time To Buy And Sell Stock 買賣股票最佳時(shí)機(jī)

    摘要:關(guān)鍵字,,算法,,動(dòng)態(tài)規(guī)劃,上關(guān)于主題的題目有四個(gè)這四個(gè)題目難度依次遞增。其中第四個(gè)問(wèn)題是尋求一個(gè)通解,在給定和最大買賣次數(shù)的情況下,求最大收益。首先大致的解題方向是動(dòng)態(tài)規(guī)劃,這個(gè)應(yīng)該不難想到。之后就是怎么找到狀態(tài),怎么列狀態(tài)轉(zhuǎn)移方程。 關(guān)鍵字:leetcode,Best Time To Buy And Sell Stock,算法,algorithm,動(dòng)態(tài)規(guī)劃,dynamic prog...

    elliott_hu 評(píng)論0 收藏0
  • [LeetCode]Best Time to Buy and Sell Stock with Coo

    摘要:分析因?yàn)楫?dāng)前日期買賣股票會(huì)受到之前日期買賣股票行為的影響,首先考慮到用解決。所以我們可以用兩個(gè)數(shù)組分別記錄當(dāng)前持股跟未持股的狀態(tài)。 Best Time to Buy and Sell Stock with Cooldown Say you have an array for which the ith element is the price of a given stock on ...

    xcc3641 評(píng)論0 收藏0
  • LeetCode 309. Best Time to Buy and Sell Stock with

    摘要:示例輸入輸出解釋對(duì)應(yīng)的交易狀態(tài)為買入賣出冷凍期買入賣出思路這道題使用動(dòng)態(tài)規(guī)劃。狀態(tài)表示當(dāng)天休息能夠獲得的最大價(jià)值,表示當(dāng)天持有股票能夠獲得的最大價(jià)值,表示當(dāng)天持有股票能夠獲得的最大價(jià)值。 Description Say you have an array for which the ith element is the price of a given stock on day i. ...

    劉明 評(píng)論0 收藏0
  • Leetcode188. Best Time to Buy and Sell Stock IV

    摘要:題目要求有一個(gè)整數(shù)數(shù)組,每一位上的值代表那一天的股票價(jià)格。現(xiàn)在假設(shè)最多能夠進(jìn)行次交易,問(wèn)最大的收入是多少思路和代碼這里采用了動(dòng)態(tài)編程的思想。 題目要求 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 t...

    pingink 評(píng)論0 收藏0
  • LeetCode-Best Time to Buy and Sell Stock

    摘要:注意你不能在買入股票前賣出股票。示例輸入輸出解釋在這種情況下沒(méi)有交易完成所以最大利潤(rùn)為。解答這里要注意的一點(diǎn)就是不能直接求出最大的和最小的然后相減得出結(jié)果,因?yàn)橘I和賣是由順序關(guān)系的,買必須在賣之前,代碼如下 發(fā)布自Kindem的博客,歡迎大家轉(zhuǎn)載,但是要注意注明出處 題目 給定一個(gè)數(shù)組,它的第 i 個(gè)元素是一支給定股票第 i 天的價(jià)格。 如果你最多只允許完成一筆交易(即買入和賣出一支股...

    FullStackDeveloper 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<