此阶段给自己定的目标是:做过的这些题每天坚持继续刷二遍,每道题做过之后开始尝试多解法尝试解题。上一阶段是感知都有什么题目,此阶段主要系统化常规题解套路知识,牢记牢记此阶段目的。
题号:322
var coinChange = function (coins, amount) {
if (amount == 0) {
return 0
}
//最大值填充数组方便下面min的比较
let dptable = new Array(amount + 1).fill(Number.MAX_VALUE)
for (let i = 0; i < dptable.length; i++) {
//现阶段决策挑选硬币
for (let j = 0; j < coins.length; j++) {
let coin = coins[j]
if (i - coin == 0) {
//刚好一个硬币能满足所求就直接为1了
dptable[i] = 1
break
} else if (i - coin > 0) {
dptable[i] = Math.min(dptable[i - coin] + 1, dptable[i])
} else {
//当前选择的硬币大于amount就不满足题意了跳过该选择
continue
}
}
}
return dptable[dptable.length - 1] == Number.MAX_VALUE ? -1 : dptable[dptable.length - 1]
};
题号:518
//完全背包
//观察发现一些变量因子,这些变量因子就是我们在每一阶段做决策要依据的因素
//动态规划思考的时候要从上到下的角度,状态转移方程编写是从下到上
var change = function (amount, coins) {
//dptable 含义:从前i个硬币中选择一些硬币是的额度为j的组合
let dptable = new Array(coins.length + 1)
for (let i = 0; i < dptable.length; i++) {
let arr = new Array(amount + 1)
dptable[i] = arr
}
for (let i = 0; i < dptable.length; i++) {
for (let j = 0; j < dptable[0].length; j++) {
if (i == 0) {
//i==0 0个硬币凑指定金额
if (j == 0) {
//0个硬币凑0金额组合为1
dptable[i][j] = 1
} else {
//0个硬币凑不为0的金额组合永远不可能
dptable[i][j] = 0
}
} else {
//i!=0的情况下
//从前i个硬币中选,凑够金额为j
//站在这个点上的决策是:当前的第i个硬币我不用,那么我从第i-1个硬币中找到满足
//金额为j的的数量和我选第i个硬币的前提下满足j - coins[i - 1]的金额的组合(可能没有)
if (j - coins[i - 1] >= 0) {
dptable[i][j] = dptable[i - 1][j] + dptable[i][j - coins[i - 1]]
} else {
dptable[i][j] = dptable[i - 1][j]
}
}
}
}
return dptable[dptable.length - 1][dptable[0].length - 1]
};
题号:300
var lengthOfLIS = function (nums) {
if (nums.length == 1) {
return 1
}
//dptable :以元素i结尾的最大所求值
let dptable = new Array(nums.length).fill(0)
let result = 0
for (let i = 0; i < nums.length; i++) {
if (i == 0) {
dptable[i] = 1
} else {
dptable[i] = 1
for (let j = 0; j < i; j++) {
if (nums[i] > nums[j]) {
dptable[i] = Math.max(dptable[i], dptable[j] + 1)
}
}
result = Math.max(result, dptable[i])
}
};
return result
}