算法-----对动态规划对研究

动态规划是⼀种常⻅的「算法设计技巧」,并没有什么⾼深莫测,⾄于各种⾼⼤上的术语,那是吓唬别
⼈⽤的,只要你亲⾃体验⼏把,这些名词的含义其实显⽽易⻅,再简单不过了。
⾄于为什么最终的解法看起来如此精妙,是因为动态规划遵循⼀套固定的流程:递归的暴⼒解法 -> 带
备忘录的递归解法 -> ⾮递归的动态规划解法。这个过程是层层递进的解决问题的过程,你如果没有前
⾯的铺垫,直接看最终的⾮递归动态规划解法,当然会觉得⽜逼⽽不可及了。
举个⼩栗⼦,斐波那契数列
 
暴⼒递归fifib
function fib(n){
if(n==1 || n==2) return 1
return fib(n-1) + fib(n-2)
}
中间存储fifib
 
function fib(n){
let memo = []
return helper(memo, n)
}
function helper(memo, n){
if(n==1 || n==2){
// 前两个
return 1
}
// 如果有缓存,直接返回
if (memo[n]) return memo[n];
// 没缓存
memo[n] = helper(memo, n - 1) + helper(memo, n - 2)
return memo[n]
}
 
动态规划fifib
// 斐波那契
function fib(n){
let dp = []
dp[1] = dp[2] = 1
for (let i = 3; i <=n; i++) {
dp[i] = dp[i - 1] + dp[i - 2];
}
return dp[n]
}
动态规划找零
 
class Change{
constructor(changeType){
this.changeType = changeType
this.cache = {}
}
makeChange (amount) {
let min = []
if (!amount) {
return []
}
if (this.cache[amount]) { // 读缓存
return this.cache[amount]
}
for (let i = 0; i < this.changeType.length; i++) {
const leftAmount = amount - this.changeType[i]
let newMin
if (leftAmount >= 0) {
newMin = this.makeChange(leftAmount) // 这⼀句是动态规划的提现
}
if (leftAmount >= 0
&& (newMin.length < min.length - 1 || !min.length)) { // 如果存在更
⼩的找零硬币数, 则执⾏后⾯语句
min = [this.changeType[i]].concat(newMin)
}
}
return this.cache[amount] = min
}
}
const change = new Change([1, 5, 10, 20,50,100])
console.log(change.makeChange(2))
console.log(change.makeChange(5))
console.log(change.makeChange(13))
console.log(change.makeChange(35))
console.log(change.makeChange(135))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

 

posted @ 2020-06-02 13:49  又回到了起点  阅读(229)  评论(0编辑  收藏  举报