[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万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章