一些动态规划的练习题
Posted GoldenaArcher
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一些动态规划的练习题相关的知识,希望对你有一定的参考价值。
一些动态规划的练习题
大部分题目是分治的题目,所以 cv 了一下题目……每道题前面大概也空个四五行这样……?
top down 和 bottom up 都做了
-
fib
斐波那契数字(同样也可以求序列来着)
/** * * * * * * * * */ const memoFibTopDown = (n: number, memo: number[]): number => if (n === 1) return 0; if (n === 2) return 1; if (!memo[n]) memo[n] = memoFibTopDown(n - 1, memo) + memoFibTopDown(n - 2, memo); return memo[n]; ; console.log(memoFibTopDown(6, [])); console.log(memoFibTopDown(7, [])); // avoid recursion const memoFibBottomUp = (n: number): number => const memo = new Array(n + 1).fill(0); memo[2] = 1; for (let i = 2; i < n; i++) memo[i + 1] = memo[i] + memo[i - 1]; return memo[n]; ; console.log(memoFibBottomUp(6)); console.log(memoFibBottomUp(7));
-
number factor
/** * * * * */ // number factor // problem // Given N, find the number of ways to express N as a sum of 1, 3 and 4. // example // N = 4, res = 4 - 4, 1, 3, 3, 1, 1, 1, 1, 1 // N = 4, res = 6 -4, 1, 1, 4, 1, 3, 1, 3, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1 const numFactorTopDown = (num: number): number => const memo: number[] = new Array(num + 1).fill(0); const expression = [1, 3, 4]; const recursion = (num: number): number => if (num < 0) return 0; if (num === 0) return 1; if (memo[num]) return memo[num]; let sum = 0; for (const exp of expression) sum += recursion(num - exp); memo[num] = sum; return sum; ; recursion(num); return memo[num]; ; console.log(numFactorTopDown(4)); console.log(numFactorTopDown(5)); console.log(numFactorTopDown(6)); console.log(numFactorTopDown(7)); const numFactorBottomUp = (num: number): number => const memo = new Array(num + 1).fill(0); const expression = [1, 3, 4]; for (const exp of expression) memo[exp] = 1; for (let i = 1; i <= num; i++) let sum = memo[i]; for (const exp of expression) sum += memo[i - exp] ?? 0; memo[i] = sum; return memo[num]; ; console.log(numFactorBottomUp(4)); console.log(numFactorBottomUp(5)); console.log(numFactorBottomUp(6)); console.log(numFactorBottomUp(7));
-
house robber
/** * * * * */ // house robber // problem // given n number of houses along the street with some amount of money // adjacent hoouses cannot be stolen // find the max amount that can be stolen // ex1: [6, 7, 1, 30, 8, 2, 4], res: [_, 7, _, 30, _, _, 4] = 41 // it can be divided: // max(6 + f([1, 30, 8, 2, 4], 0 + f([7, 1, 30, 8, 2, 4])) const houseRobberTD = (houses: number[]): number => const memo = new Array(houses.length).fill(0); const recursion = (num: number): number => if (num >= houses.length) return 0; if (num === houses.length - 1) return houses[houses.length - 1]; if (memo[num]) return memo[num]; const pick = houses[num] + recursion(num + 2); const noPick = recursion(num + 1); memo[num] = Math.max(pick, noPick); return memo[num]; ; return recursion(0); ; console.log(houseRobberTD([6, 7, 1, 30, 8, 2, 4])); console.log(houseRobberTD([1, 2, 3, 1])); console.log(houseRobberTD([2, 7, 9, 3, 1])); console.log(houseRobberTD([1])); const houseRobberBU = (houses: number[]): number => const memo = new Array(houses.length).fill(0); for (let i = 0; i < houses.length; i++) const pick = houses[i] + (memo[i - 2] ?? 0); const notPick = memo[i - 1] ?? 0; memo[i] = Math.max(pick, notPick); return memo[houses.length - 1]; ; console.log(houseRobberBU([6, 7, 1, 30, 8, 2, 4])); console.log(houseRobberBU([1, 2, 3, 1])); console.log(houseRobberBU([2, 7, 9, 3, 1])); console.log(houseRobberBU([1]));
-
convert one string to another
/** * * * * */ // convert one string to another // problem // given 2 strings s1 and s2 // converting s2 to s1 using celete, insert, or replace operations // find the minimum count of edit operations // ex1, "catch" & "carsh", res = 1, replace 'r' with 't' // ex2, "table" & "tbres", res = 3, insert '2 at index 1, replace 'r' with 'l', and delete 's' // min(num_of_op_performed + f(s1[1:], s2[1:])) // in DP, use 2D array to remember all the operation like: // s1 // s2 const convertStringTD = (s1: string, s2: string): number => const memo: number[][] = Array.from(new Array(s1.length), () => new Array(s2.length).fill(0) ); const recursion = (i: number, j: number): number => if (i === s1.length) return s2.length - j; if (j === s2.length) return s1.length - i; if (s1[i] === s2[j]) return recursion(i + 1, j + 1); if (!memo[i][j]) const insertOp = recursion(i + 1, j); const deleteOp = recursion(i, j + 1); const replaceOp = recursion(i + 1, j + 1); memo[i][j] = 1 + Math.min(insertOp, deleteOp, replaceOp); return memo[i][j]; ; recursion(0, 0); return recursion(0, 0); ; console.log(convertStringTD('', 'abc')); console.log(convertStringTD('abc', '')); console.log(convertStringTD('abc', 'd')); console.log(convertStringTD('catch', 'carch')); console.log(convertStringTD('table', 'tbres')); console.log(convertStringTD('dable', 'tbres')); const convertStringBU = (s1: string, s2: string): number => const memo: number[][] = Array.from(new Array(s1.length + 1), () => new Array(s2.length + 1).fill(0) ); for (let i = 0; i <= s1.length; i++) memo[i][0] = i; for (let j = 0; j <= s2.length; j++) memo[0][j] = j; for (let i = 1; i <= s1.length; i++) for (let j = 1; j <= s2.length; j++) if (s1[i - 1] === s2[j - 1]) memo[i][j] = Math.min( memo[i - 1][j - 1], memo[i - 1][j], memo[i][j - 1] ); continue; // insert op const insertOp = memo[i - 1][j]; // delete op const deleteOp = memo[i][j - 1]; // replace op const replaceOp = memo[i - 1][j - 1]; memo[i][j] = Math.min(insertOp, deleteOp, replaceOp) + 1; console.log(memo); return memo[s1.length][s2.length]; ; console.log(convertStringBU('catch', 'carch')); console.log(convertStringBU('dable', 'tbres')); console.log(convertStringBU('table', 'tbres')); console.log(convertStringBU('table', 'tbrltt'));
-
zero one knapsack problem
这道题其实是个非典型 DP,用 D&C 和 DP 其实没什么区别……就算用 DP 也没有可以重复地柜的子问题,不过还是试着写了一下。
/** * * * * */ // zero one knapsack problem // problem // given weight and profit of n items // find the maximum profit given capacity of C // items cannot be broken // profit: [31, 26, 17, 72] // weight: [ 3, 1, 2, 5] // kapacity: 7 // res = 26 + 72 = 98 // max(0 + profit[1, ..., n], profit[0] + profit[1, ..., n]) const zeroOneKnapsackProblemTD = ( profits: number[], weights: number[], capacity: number ): number => const memo = new Map(); const recursion = (n: number, capacity: number): number => if (capacity <= 0) return 0; if (n === profits.length - 1) return weights[n] > capacity ? 0 : profits[n]; const key = `$n,$capacity`; if (!memo.has(key)) let takenProfit = 0, takenCapacity = 0; if (capacity > weights[n]) takenCapacity = capacity - weights[n]; takenProfit += profits[n]; memo.set( key, Math.max( recursion(n + 1, capacity), takenProfit + recursion(n + 1, takenCapacity) ) ); return memo.get(key); ; return recursion(0, capacity); ; console.log(zeroOneKnapsackProblemTD动态规划:零钱兑换问题(javascript求解)