这是我参与2022首次更文挑战的第36天,活动详情查看:2022首次更文挑战
题目描述
提供一个数组prices,然后索引代表的是第几天,对应的值代表的是股票当天的价格。
然后你需要选择在第几天买入股票,然后在第几天卖出股票。
返回所赚到的最大的收益。
如果不能赚到收益,则返回0。
注意:卖出时间要比买入时间晚。 你不能在没买入的时候就卖出。不符合常理。
举个例子:
prices: [5,4,1,2,3]
返回: 2 (3-1,不是5-1,因为要先买入,再卖出)
prices: [5,4,3,2,1]
返回: 0 (因为都是递减的,没有最大收益)
prices的长度大于等于1,小于等于100000。 每一项的值大于等于0,小于等于10000。
思路分析
第一种方法(错误)
这道题按照常规方法来想,就是定义一个变量res,记录最大的收益。
然后对数组进行嵌套遍历, 第一层从0开始遍历,第二层从第一层的索引开始遍历
然后两个索引对应的值相减,如果结果大于0,并且大于res,则覆盖res。
否则继续遍历。
等到遍历结束的时候,得到的res就是最大的收益。
代码如下:
/**
* @param {number[]} prices
* @return {number}
*/
var maxProfit = function (prices) {
let res = 0
for (let i = 0; i < prices.length - 1; i++) {
for (let j = i + 1; j < prices.length; j++) {
const profit = prices[j] - prices[i]
if (profit > 0 && profit > res) {
res = profit
}
}
}
return res
};
但是我们忽略了题目的补充条件,prices的长度是有可能达到100000的,所以这样嵌套遍历,耗时太长。
导致超出时间限制。
那能不能一次遍历就能实现的呢?
可以
第二种方法(正确)
我们定义2个变量,res代表最大的收益,默认是0,max为当前遍历到的最大元素, 默认是最后一个元素。
我们从后往前遍历
如果当前遍历的元素比max大,则把它赋值给max,替换max。
如果当前遍历的元素比max小,则把max和它相减,结果与res比较,如果比res大则替换res。
这样子遍历结束后,可以找到最大的那个元素,和最大的收益。如果没有找到,则res是0。
返回res即可。
代码如下:
/**
* @param {number[]} prices
* @return {number}
*/
var maxProfit = function (prices) {
const len = prices.length
let res = 0
let max = prices[len - 1]
for (let i = len - 1; i >= 0; i--) {
if (prices[i] > max) {
max = prices[i]
} else {
res = Math.max(res, max - prices[i])
}
}
return res
};