题目:
假设把某股票的价格按照时间先后顺序存储在数组中,请问买卖该股票一次可能获得的最大利润是多少?
示例1:
输入: [7,1,5,3,6,4]
输出: 5
解释: 在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。(注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格。)
示例2:
输入: [7,6,4,3,1] 输出: 0 解释: 在这种情况下, 没有交易完成, 所以最大利润为 0。
思考:
想要解决这道题,无非就是循环。按照正常情况,我们第一时间想到的就是两层循环嵌套暴力求解,但是如果我们想要一层循环就搞定呢?通过题目分析,发现卖出的最大值永远在买入的最小值之后,也就是说我们不需要考虑 min(最小值买入)之前的数据。
那么解题方法来了:
我们用一个 min 来存放当下找到的最小值,然后遍历数组,如果发现下一个数比 min 还小,那么久更新 min 的值。在这期间也定义一个 res ,用来存放利润,初始值为0,如果下一个数不比 min 小,那么就当即计算如果当前值为 最大值 时的利润,并与 res 现在的值进行比较,将较大者放入 res,以此重复,当循环结束时,res 里面存放的就是最大利润。
图解流程:
步骤:
1. 先判断一下空数组和只有一个元素的情况,直接返回0。
2. 定义一个 min ,初始值为 prices[0],定义一个 res,初始值为 0。
3. 从第二个元素开始循环遍历数组。
4. 如果发现当前的元素值小于 min ,更新 min 的值。
5. 如果发现当前元素的值不小于 min 的值,求出当前元素的利润,然后与 res 比较,较大者赋值给 res。
6. 结束循环后,res 中存放的就是最大利润。
具体代码:
class Solution {
public int maxProfit(int[] prices) {
if(prices == null || prices.length < 2){
return 0;
}
//先将数组的第一个数当作最小值
int min = prices[0];
//存放利润
int res = 0;
for(int i = 1; i < prices.length; i++){
//如果当前这个数比min还小,更新
if(prices[i] < min){
min = prices[i];
}else{
//不小,先求出当前值与min的差值
int tmp = prices[i] - min;
//差值与res比较
if(res < tmp){
//res小就更新
res = tmp;
}
}
}
//最终res存放的就是最大的差值
return res;
}
}
LeetCode 测试结果:
总结:
暴力求解固然可以解决问题,但有时我们往往追求的是更高的效率。