LeetCode-Java:122. 買賣股票的最佳時機Ⅱ

另世我發表於2023-12-03

題目

給你一個整數陣列 prices ,其中 prices[i] 表示某支股票第 i 天的價格。

在每一天,你可以決定是否購買和/或出售股票。你在任何時候 最多 只能持有 一股 股票。你也可以先購買,然後在 同一天 出售。

返回 你能獲得的 最大 利潤

示例 1:

輸入:prices = [7,1,5,3,6,4]
輸出:7
解釋:在第 2 天(股票價格 = 1)的時候買入,在第 3 天(股票價格 = 5)的時候賣出, 這筆交易所能獲得利潤 = 5 - 1 = 4 。
     隨後,在第 4 天(股票價格 = 3)的時候買入,在第 5 天(股票價格 = 6)的時候賣出, 這筆交易所能獲得利潤 = 6 - 3 = 3 。
     總利潤為 4 + 3 = 7 。

示例 2:

輸入:prices = [1,2,3,4,5]
輸出:4
解釋:在第 1 天(股票價格 = 1)的時候買入,在第 5 天 (股票價格 = 5)的時候賣出, 這筆交易所能獲得利潤 = 5 - 1 = 4 。
     總利潤為 4 。

示例 3:

輸入:prices = [7,6,4,3,1]
輸出:0
解釋:在這種情況下, 交易無法獲得正利潤,所以不參與交易可以獲得最大利潤,最大利潤為 0 。

這道題目和121的區別在於,購買者同時只能持有一隻股票,但是可以交易多次,比如示例1

①暴力解,程式碼來源自leetcode,主要思想為遞迴的方式,返回到葉子結點的一次收益,判斷收益是否比之前的最大收益要大,如果更大的話更換儲存的最大收益值。本題遍歷了所有的情況,不適用於資料量較多的情況,故用例時間超出

(圖片來源自leetcode,作者liweiwei1419)

class Solution {
    private int maxprofit;
    public int maxProfit(int[] prices) {
        if(prices.length<2) return 0;
        this.maxprofit=0;
        dfs(prices,0,0,maxprofit);
        return this.maxprofit;
    }
    private void dfs(int[] prices,int index,int status,int profit){
        //各個元素含義:價格陣列,當前下標,是否有股票,當前收益
        if(index==prices.length){
            this.maxprofit=Math.max(this.maxprofit,profit);//取當前收益和歷史最大收益二者之間的最大值
            return;
        }
        dfs(prices,index+1,status,profit);//深度優先搜尋,對應圖當中所有樹取左邊的結果
        if(status==0){
            //如果沒有購入的話,可以考慮購入一下,購入的話就得減去當日價格,然後陣列+1指向下一層
            dfs(prices,index+1,1,profit-prices[index]);
        }
        else{
            //如果已經購入,可以考慮賣出一下,賣出+當日價格,然後陣列+1指向下一層
            dfs(prices,index+1,0,profit+prices[index]);
        }
    }
}

②動態規劃,二維陣列,題解思路來源leetcode,建立一個二維陣列,超過28.33%的使用者

二維陣列a[i][j]表示為第i狀態為j的最大收益情況(j表示是否持股,0不持股,1持股)

class Solution {
    private int maxprofit;
    public int maxProfit(int[] prices) {
        if(prices.length<2) return 0;
        int [][]dp=new int[prices.length][2];
        dp[0][0]=0;
        dp[0][1]=0-prices[0];
        for(int i=1;i<prices.length;i++){
            //區域性最優解,每次從上一步得到賣出/買進或者保持不動的最大值
            dp[i][0]=Math.max(dp[i-1][0],dp[i-1][1]+prices[i]);
            dp[i][1]=Math.max(dp[i-1][1],dp[i-1][0]-prices[i]);
        }
        return dp[prices.length-1][0];//最後一天不持有的情況肯定是最大值
    }
}

③如果前一天買進,今天賣出可以賺錢的話就+

class Solution {
    private int maxprofit;
    public int maxProfit(int[] prices) {
        if(prices.length<2) return 0;
        int max=0;
        for(int i=1;i<prices.length;i++){
            if(prices[i]-prices[i-1]>0){
                max+=prices[i]-prices[i-1];
            }
        }
        return max;
    }
}