这两题的共同点就是状态只有日期(只有 i
的变化才会导致结果的变化),即数组索引 i
。
做这类题其实只要能写出 dfs 解法,然后在其基础上优化,最后一定能通过测试。
为什么建议先写 dfs 呢?因为 dfs 解法更符合我们的思维方式,更容易写出题解。
找到了状态 i,就是找到了 dfs 函数的参数,即:
function dfs(i){
}
每一个 dfs(i)
中都有两个状态值:有股票状态和没有股票状态的钱。
所以函数的返回值为:
function dfs(i){
return [当前没股票的钱,当前有股票的钱]
}
/**
* @param {number[]} prices
* @return {number}
*/
var maxProfit = function(prices) {
function dfs(i){
// 边界
if(i < 0) return [0,Number.MIN_SAFE_INTEGER]
// 当前没有股票状态为:
// 前一天没有股票和前一天没有股票今天卖出,两者中的最优值
// 当前有股票状态为:
// 前一天没有股票和前2天没有股票今天买入,两者中的最优值
const status_0 = Math.max(dfs(i-1)[0],dfs(i-1)[1]+prices[i])
const status_1 = Math.max(dfs(i-1)[1],dfs(i-2)[0]-prices[i])
return [status_0,status_1]
}
return dfs(prices.length-1)[0]
-----------------------分界线----------------------------
// 优化:
// 通过 dfs 函数可以知道,其实只需要保存前两天的状态
// 因为 dfs(i) 只与 dfs(i-1) 和 dfs(i-2)有关
// 使用自底向上的动态规划,对暴力 dfs 进行优化
let prev_1 = [0,Number.MIN_SAFE_INTEGER], prev_2 = [0,Number.MIN_SAFE_INTEGER]
for(let i = 0, len = prices.length; i<len; i++){
const status_0 = Math.max(prev_1[0],prev_1[1]+prices[i])
const status_1 = Math.max(prev_1[1],prev_2[0]-prices[i])
prev_2 = prev_1
prev_1 = [status_0,status_1]
}
return prev_1[0]
};
/**
* @param {number[]} prices
* @param {number} fee
* @return {number}
*/
var maxProfit = function(prices, fee) {
function dfs(i){
// 边界值
if(i < 0) return [0,Number.MIN_SAFE_INTEGER]
// 当前没有股票为:
// 前一天没有股票和前一天没有股票今天卖出再减去手续费,两者中的最优值
// 当前有股票为:
// 前一天没有股票和前一天没有股票今天买入,两者中的最优值
const status_0 = Math.max(dfs(i-1)[0],dfs(i-1)[1]+prices[i]-fee)
const status_1 = Math.max(dfs(i-1)[1],dfs(i-1)[0]-prices[i])
return [status_0,status_1]
}
return dfs(prices.length-1)[0]
-----------------------分界线----------------------------
// 优化:
// 通过 dfs 函数可以知道,其实只需要保存前一天的状态
// 因为 dfs(i) 只与 dfs(i-1)有关
// 使用自底向上的动态规划,对暴力 dfs 进行优化
let prev = [0,Number.MIN_SAFE_INTEGER]
for(let i = 0, len = prices.length; i<len; i++){
const status_0 = Math.max(prev[0],prev[1]+prices[i]-fee)
const status_1 = Math.max(prev[1],prev[0]-prices[i])
prev = [status_0,status_1]
}
return prev[0]
};
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。