[121] Best Time to Buy and Sell Stock

1. 題目描述

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.

Example 1:
Input: [7, 1, 5, 3, 6, 4]
Output: 5

max. difference = 6-1 = 5 (not 7-1 = 6, as selling price needs to be larger than buying price)
Example 2:
Input: [7, 6, 4, 3, 1]
Output: 0

In this case, no transaction is done, i.e. max profit = 0.

讀題讀了半天,一開始沒有理解這個題目是什麼意思。題目的意思是,給定一個數組,數組裏的值爲每天產品的價格,你可以進行一次貿易,即一買一賣,如何從這一次貿易中獲得最大的利潤?即從最低價格時買入,從最高價格時賣出。當然從例子看來,如果一直沒有出現價格較低的元素,即當這個商品一直降價的時候,是不會發生買賣的,利潤爲0。

2. 解題思路

這個題目我覺得是一個動態規劃的問題,一般求最優解的問題都是動態規劃的範疇。那麼只需要找到他的遞推函數即可。問題可以被分解爲當前數和後面所有數中的最大值進行比較求值的問題,只要找出這些值中最大的值即可。如[7,1,5,3,6,4]可以被看成[7[1,[5,[3,[6,[4]]]]]],首先對[6,[4]]進行比較6>4不會產生利潤,並且對當前最大值進行賦值,之後使用前一個數與最大值進行比較,如果大於就不會產生利潤,如果小就記錄利潤中較大的一個。

當前計算 當前最大值 當前最大利潤
[6,[4]] 6 0
[3,[6]] 6 3
[5,[6]] 6 3
[1,[6]] 6 5
[7,[6]] 6 5

因爲之前一直對遞歸掌握的不好,所以最近對遞歸有點魔怔了,什麼都想用遞歸。結果這道題就在數組有10000個元素的時候成功StackOverflow啦。其實仔細想想這個遞推過程完全可以用一個循環來代替,省時省力省空間。

3. Code

// Code1:使用遞歸,Cause stack overflow :(
public class Solution {
    public int maxProfit(int[] prices) {
        // 不會產生任何貿易
        if(prices.length <= 1)
        {
            return 0;
        }
        int last = prices.length - 1;
        return getMax(last-1, prices, prices[last], 0);
    }

    private int getMax(int n, int[] prices , int currentMax, int profit)
    {
        if(n < 0)
        {
            return profit;
        }
        // 如果前面一個大於後面的最大值,將當前最大值賦值爲前面一個,利潤爲0
        if(prices[n] >= currentMax)
        {
            return getMax(n-1, prices, prices[n], 0);
        }
        // 如果前面的值小於後面的最大值,將最大值賦值爲當前最大值,利潤爲當前利潤和之前利潤中較大的一個
        else{
            return getMax(n-1, prices, currentMax, Math.max(profit, currentMax - prices[n]));
        }
    }
}
// Code2:Accepted,直接使用for循環,不使用遞歸
public class Solution {
    public int maxProfit(int[] prices) {
        // 不會產生任何貿易
        if(prices.length <= 1)
        {
            return 0;
        }
        int last = prices.length - 1;
        int profit = 0;
        int currentMax = prices[last];
        for(int i = last - 1; i >= 0; --i)
        {
            // 如果當前金額大於currentMax,給currentMax賦值
            if(prices[i] >= currentMax)
            {
                currentMax = prices[i];
            }
            // 如果小於currentMax,計算利潤,將利潤賦值爲比較大的那個
            else
            {
                profit = Math.max(profit, currentMax - prices[i]);
            }
        }
        return profit;
    }
}
發佈了79 篇原創文章 · 獲贊 58 · 訪問量 15萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章