题目
给定一个都为正数的数组和一个数值n,求构成n的最小数量
- 通过递归过程来保存每一次的硬币数量,如果无效会通过返回值 -1 来抵消
// -1表示无效值,0表示有效
function process(arr, index, rest) {
if (rest < 0) {
return -1;
}
if (rest === 0) {
return 0;
}
if (index === arr.length) {
return -1;
}
const no = process(arr, index + 1, rest);
const yes = process(arr, index + 1, rest - arr[index]);
if (no == -1 && yes == -1) {
// 要或不要当前硬币都无解
return -1;
} else {
if (no == -1) {
return yes + 1; // 在要当前硬币下的解
}
if (yes == -1) {
return no; // 不要当前硬币下的解
}
return Math.min(no, yes + 1); // 在要或不要都有解的情况下取最小值
}
}
进阶2:记忆化搜索
const dp = [];
for (let i = 0; i < arr.length; i++) {
for (let j = 0; j < target; j++) {
dp[i][j] = -2;
}
}
// -1表示无效值,0表示有效
function process(arr, index, rest) {
if (rest < 0) {
return -1;
}
if (dp[index][rest] !== -2) {
return dp[index][rest];
}
if (rest === 0) {
dp[index][rest] = 0;
} else if (index === arr.length) {
dp[index][rest] = -1;
} else {
const no = process(arr, index + 1, rest);
const yes = process(arr, index + 1, rest - arr[index]);
if (no == -1 && yes == -1) {
// 要或不要当前硬币都无解
dp[index][rest] = -1;
} else {
if (no == -1) {
dp[index][rest] = yes + 1; // 在要当前硬币下的解
} else if (yes == -1) {
dp[index][rest] = no; // 不要当前硬币下的解
} else {
dp[index][rest] = Math.min(no, yes + 1); // 在要或不要都有解的情况下取最小值
}
}
}
return dp[index][rest];
}
进阶3:严格表结构