[121] Best Time to Buy and Sell Stock

19 篇文章 1 订阅
9 篇文章 1 订阅

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]]60
[3,[6]]63
[5,[6]]63
[1,[6]]65
[7,[6]]65

因为之前一直对递归掌握的不好,所以最近对递归有点魔怔了,什么都想用递归。结果这道题就在数组有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;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值