给定一个数组
prices,它的第i个元素prices[i]表示一支给定股票第i天的价格。你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。
返回你可以从这笔交易中获取的最大利润。如果你不能获取任何利润,返回
0。
解法1 暴力解法
思路
最简单的解法就是两层循环,第二层寻找 i + 1 开始后面的最大值,顺便更新答案。
但这样不能 AC ,只能通过 202 个用例。
代码
function maxProfit(prices: number[]): number {
let result = 0;
for (let i = 0; i < prices.length; i++) {
for (let j = i + 1; j < prices.length; j++) {
result = Math.max(result, prices[j] - prices[i]);
}
}
return result;
};
时空复杂度
时间复杂度:O(n^2)
空间复杂度:O(1)
解法2 后缀最大值
思路
答案其实寻找的是当前的值和后续的某一个值的最大值,那我们是不是可以通过遍历出后缀数组,即每个 i 的后面的最大值。
这样再次遍历这两个数组,就可以得出最大值的答案。
代码
function maxProfit(prices: number[]): number {
let result = 0;
const n = prices.length;
const suffix = new Array(n).fill(0);
suffix[n - 1] = prices[n - 1];
for (let i = n - 2; i >= 0; i--) {
suffix[i] = Math.max(suffix[i + 1], prices[i]);
}
for (let i = 0; i < prices.length; i++) {
result = Math.max(result, suffix[i] - prices[i]);
}
return result;
};
时空复杂度
时间复杂度:O(n)
空间复杂度:O(n)
解法3 前缀最小值
思路
上个方法的思路是用当前 i 后续的最大值减去 prices[i] ,这样需要额外的后缀最大值空间,而我们可不可以省略这个呢?
我们换个思路,当我们得知当前 i 前面的最小值,是不是也可以得出一个差值,我们在遍历中更新这个差值是不是就得到了答案,每次遍历到当前 prices[i] 比前面的最小值 low 小时,我们后续的差值是不会比这个大的,所以需要更新 low 。
代码
function maxProfit(prices: number[]): number {
let result = 0;
let low = prices[0];
for (let i of prices) {
result = Math.max(result, i - low);
if (i < low) {
low = i;
}
}
return result;
};
时空复杂度
时间复杂度:O(n)
空间复杂度:O(1)