今天南京下雨了,雨天的巷子特别有感觉
正题
给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。
你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。
返回你可以从这笔交易中获取的最大利润。如果你不能获取任何利润,返回 0 。
示例 1:
输入:[7,1,5,3,6,4]
输出:5
解释:在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。
注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格;同时,你不能在买入前卖出股票。
示例 2:
输入:prices = [7,6,4,3,1]
输出:0
解释:在这种情况下, 没有交易完成, 所以最大利润为 0。
乍一看题目还是比较简单的,无非就是求得数组中最大的差是多少,限制条件就是最小值要在最大值的左边。因为天数是不可能倒着过的。第一直觉就是做暴力破解,循环遍历这个数组,找到每一个元素右侧对应能买卖股票的最佳时机。
如上图所示:
7 能对应的最大售出值不存在
1 能对应的最大售出值是6
5 能对应的最大售出值是6
3 能对应的最大售出值是6
6 能对应的最大售出值不存在
4 能对应的最大售出值不存在
所以可以得出方法一: 暴力枚举法
var maxProfit = function(prices) {
let res = 0
for(let index = 0 ; index < prices.length - 1; index++) {
const n1 = prices[index]
let max = prices[index + 1]
for (let j = index + 1 ; j < prices.length; j++) {
max = max > prices[j] ? max : prices[j]
}
res = res > max - n1 ? res : max - n1
}
return res
};
但是以上这个方法可以说是对性能毫无要求,我们可以用一个非常大的数组作为测试用例。
可以看到他的用是时间已经超过了5秒多,这在实际运用中可以说是效率极低的。那么能不能讲结果控制在毫秒级呢?
方法二: 动态规划法
动态规划的核心是每实现一步都会有状态的改变,从而判断下一步操作。那么我们可以给定一个数组dpList,记录原数组对应下标的数的最大利润。
var maxProfit = function(prices) {
let dpList = new Array(prices.length).fill(0)
let min = prices[0]
for (let i = 1 ; i < prices.length ; i++) {
if (prices[i] > min) {
dpList[i] = prices[i] - min
} else {
dpList[i] = 0
min = prices[i]
}
}
return Math.max(...dpList)
}
同样的测试用例,仅仅只用了80ms,远比暴力枚举效率要高出很多。