关于LeetCode中Best Time to Buy and Sell Stock一题的理解


【关于LeetCode中Best Time to Buy and Sell Stock一题的理解】题目如下:

Say you have an array for which the ith element is the price of a given stock on dayi.
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: 5max. 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: 0In this case, no transaction is done, i.e. max profit = 0.

题目的意思是给定一个数组,这个数组代表某只股票在某些天内价格变动的情况。例如说看Example1中例子,股票在第一天的价格是7,第二天的价格是1。假如你在第一天买了这只股票,第二天要卖出的话肯定肯定亏钱,因为第二天股票只值1,如果卖出的话会亏6。那哪天买入股票,哪天卖出股票才能使利润达到最大呢?肯定是第二天买入股票,然后在第五天也就是价格为6的那天卖出股票,这样得到的利润最大,因为你不可能在第二天买股票然后穿越回第一天去卖,所以你不可能得到7-1=6的利润。我们的任务就是要写一个程序,给定每天股票的价格,求在这个数组的时间段内你可以达到的最大利润是多少。这道题也是我思考时间非常长的一道题,大前天晚上看到这道题,然后刚才才做出来,还是在吃饭的时候想到的解决方案.......看来,想出算法还真是一个玄学问题。
最开始我的思路是遍历所有可能性,也就是使用双重循环。显然,刷了十几天LeetCode也知道它的尿性,要是这么简单就能通过这道题就不会上面试题了,对吧。最后肯定也是毫无疑问的超时,然后我就开始思考其他方法。中途想过把数组中的“股票价格”先按价格排序会不会有什么不同,但是后来发现确实没什么卵用,其实这些价格已经按时间顺序排好序了,在搞出一个价格排序似乎也没什么意义。刚才在食堂吃饭的时候,想到是不是可以用带条件的最大值最小值来计算这个利润,后来思考了一下觉得是可行的,这个条件就是价格出现的时间顺序,这些时间顺序可以作为最大最小值赋值的一个依据,当然求解利润的时候肯定也需要最大值出现在最小值后面才有意义,否则我们又得穿越回之前的某一天去了(笑)。好,先老规矩放已Accepted的代码:

public int maxProfit(int[] prices) { int profit = 0; if(prices.length==0){ return 0; } int max = prices[0]; int min = prices[0]; int max_index = 0; int min_index = 0; for(int i=0; i=max || (max_index<=min_index)){ max = prices[i]; max_index = i; } if(max_index>=min_index){ int temp = max-min; profit = profit>=temp?profit:temp; } } return profit; }

首先,在程序开头我声明了四个变量max,min,max_index,min_index。max和min的意思无需多言,max_index和min_index则分别代表最大值和最小值的下标值,这两个下标值可以帮助我们判断什么时候可以进行求proft操作,什么时候可以获得一个新的max值。直接看循环内部,最小值获取只需要看是不是比当前最小值要小,如果小的话就直接将新值赋值给min即可,不需要判断index。而最大值max则不同,如果prices[i]大于max肯定是要赋值的。但如果max_index小于min_index也是要进行赋值的,因为此时原来的最大值完全排不上用场,因为它的价格已经是过去时了,而且最总要的是是在min的过去,这是不行的,所以这种情况我们也要直接赋新值。接下来就是进行判断,条件就是最大值的下标一定要大于等于最小值的下标,原因和上面类似。计算出这个值之后要和之前的profit进行比较,这个大家都懂我就不说了。
这道题是有Editoral Solution的,里面介绍了两种方法第一种超时的,第二种和我的方法思路一样,但是更简练些,地址在这里:https://leetcode.com/articles/best-time-buy-and-sell-stock/ 。然后这里直接贴一下那种较为简练的代码,如下所示:

public int maxProfit(int prices[]) { int minprice = Integer.MAX_VALUE; int maxprofit = 0; for (int i = 0; i < prices.length; i++) { if (prices[i] < minprice) minprice = prices[i]; else if (prices[i] - minprice > maxprofit) maxprofit = prices[i] - minprice; } return maxprofit; }

如果大家还想看详细的解析(其实也不是很详细),就看戳那个Editoral Solution地址吧~


    推荐阅读