dp属于比较难的题目,主要是要推出合适的递推公式,下面总结常考的几种类型
有一些经典的题型:例如交换几次使得某种序列最长?参考网易8.20的笔试。
买卖股票
链接: link
lc121买卖股票(简单)
只交易一次,选取获得利润最大的
var maxProfit = function(prices) {
//买卖股票问题
//分为持有股票,和不持有股票的最大利润
const len = prices.length;
let dp = new Array(len).fill([0,0]);
//初始化
dp[0][0] = -prices[0];
dp[0][1] = 0;
for(let i = 1; i < prices.length; i++){
dp[i][0] = Math.max(dp[i-1][0],-prices[i]);
dp[i][1] = Math.max(dp[i-1][1],prices[i]+dp[i-1][0]);
}
return dp[len-1][1];
};
lc122买卖股票多次(中等)
var maxProfit = function(prices) {
//可以多次交易
//仍然是分为持有股票和不持有两个状态
const len = prices.length;
let dp = new Array(len).fill([0,0]);
//初始化
dp[0][0] = -prices[0];
dp[0][1] = 0;
for(let i = 1; i < len; i++){
dp[i][0] = Math.max(dp[i-1][0],dp[i-1][1] - prices[i]);
dp[i][1] = Math.max(dp[i-1][1],prices[i]+dp[i-1][0]);
}
return dp[len-1][1]
};
lc123买卖两次(困难)
var maxProfit = function(prices) {
//买卖两次,五种状态
const len = prices.length;
const dp = new Array(len).fill(0).map(()=>new Array(5).fill(0));
dp[0][1] = -prices[0];
dp[0][3] = -prices[0];
for(let i = 1; i < len; i++){
dp[i][0] = dp[i-1][0];
dp[i][1] = Math.max(dp[i-1][1],dp[i-1][0] - prices[i]);
dp[i][2] = Math.max(dp[i-1][2],dp[i-1][1]+prices[i]);
dp[i][3] = Math.max(dp[i - 1][3], dp[i - 1][2] - prices[i]);
dp[i][4] = Math.max(dp[i - 1][4], dp[i - 1][3] + prices[i]);
}
return dp[len-1][4];
};
lc714
var maxProfit = function(prices, fee) {
let dp = Array.from(Array(prices.length),()=>Array(2).fill(0));
dp[0][0] = 0 - prices[0];
for(let i = 1; i < prices.length; i++){
dp[i][0] =Math.max(dp[i-1][0],dp[i-1][1] - prices[i]);
dp[i][1] = Math.max(dp[i-1][0]+prices[i] - fee,dp[i-1][1]);
}
return Math.max(dp[prices.length - 1][0],dp[prices.length - 1][1]);
};
子序列
lc674
var findLengthOfLCIS = function(nums) {
let len = nums.length;
let left = 0;
let right = 0;
let res = 1;
while(right < nums.length){
if(nums[right] > nums[right-1]){
right++;
}else{
left = right;
right++;
}
res = Math.max(res,right - left);
}
return res;
};
var findLengthOfLCIS = function(nums) {
let len = nums.length;
let dp = new Array(len).fill(1);
let res = 1;
for(let i = 1; i < len; i++){
if(nums[i] > nums[i-1]){
dp[i] = dp[i-1]+1;
res = Math.max(dp[i],res);
}
}
return res;
};