1、递推
递推关系式(Recurrence relation),在数学上也就是差分方程,是一种递推地定义一个序列方程:序列的每一项目是定义为前若干项的函数: 像斐波那契数即为递推关系
Xn+2 = Xn+1 + Xn
与递归的区别
Recursion,指程序调用自身的编程技巧
斐波那契数列
var fib = function(n) {
arr = [0 ,1]
for(let i =2; i<= n; i++){
arr[i] = arr[i - 1] + arr[i - 2]
arr[i] %= (1e9+7)
}
return arr[n]
};
爬楼梯
var climbStairs = function(n) {
if(n<=3){
return n
}
let arr = [0,1,2,3]
for(let i = 4; i<n; i++){
arr[i] = arr[i-1] + arr[i-2]
}
return arr[n-1] + arr[n-2]
};
2、动态规划
Dynamic Programming 简称DP,是一种在数学、管理科学、计算机科学、经济学和生物信息学中使用的,通过把原问题分解为相对简单的子问题的方式求解复杂问题的方法。通常会有暴力解决以及优化解决方案,二者用时差别较大
与递推、递归
动态规划,通常离不开递推公式、递归
与数学
求值单个数值的dp题,通常会有数学公式求解法,当然这个需要较高的数学功底,这个通常在竞赛中常见,但是面试一般不做要求,面试中更多考察dp的优化版解法
动态规划解题思路
- 大事化小
- 小事化了
- 优化:记忆求值 有效求值
leetcode 746 使用最小花费爬楼梯
var minCostClimbingStairs = function(cost) {
let len = cost.length
let dp = [0, 0]
for(let i =2; i <=len ; i++){
dp[i] = Math.min(dp[i-1] + cost[i-1], dp[i-2] + cost[i-2])
}
return dp[len]
};
优化以后
var minCostClimbingStairs = function(cost) {
let len = cost.length
let prev = 0,
current = 0,
next;
for(let i =2; i <=len; i++){
next = Math.min(current + cost[i -1], prev + cost[i-2])
prev = current
current = next
}
return current
};
leetcode 121. 买卖股票的最佳时机
var maxProfit = function(prices) {
let max = 0
const len = prices.length;
for(let i=0; i<len - 1; i++){
for(let j = i+ 1; j<len; j++){
max = Math.max(max, prices[j] - prices[i])
}
}
return max
};
优化后
var maxProfit = function(prices) {
let max = 0
const len = prices.length;
let minPrice = prices[0]
for(let i=0; i<len; i++){
if(prices[i]<minPrice){
minPrice = prices[i]
}else{
max = Math.max(max, prices[i] - minPrice)
}
}
return max
};
剑指 Offer II 095. 最长公共子序列
var longestCommonSubsequence = function(text1, text2) {
const m = text1.length;
const n = text2.length;
const dp = [new Array(n + 1).fill(0)];
for(let i = 1;i <= m; i++){
const c1 = text1[i-1];
dp[i] = [0];
for(let j=1; j<=n; j++){
const c2 = text2[j-1];
if(c1 ===c2){
dp[i][j] = dp[i-1][j-1] + 1;
}else{
dp[i][j] = Math.max(dp[i-1][j], dp[i][j-1]);
}
}
}
return dp[m][n];
};
leetcode 300. 最长递增子序列
var lengthOfLIS = function(nums) {
const n = nums.length
if(n<=1){
return n;
}
const dp = new Array(n).fill(1)
let max = 1
for(let i=1; i <n ;i++){
for(let j = i-1; j>=0; j--){
if(nums[i] > nums[j]){
dp[i] = Math.max(dp[i], dp[j] + 1)
}
}
max = Math.max(dp[i], max)
}
return max
};
优化后