一些分治的练习题
Posted GoldenaArcher
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一些分治的练习题相关的知识,希望对你有一定的参考价值。
一些分治的练习题
这次因为有稍微写一下题目,所以每道题前面大概空个四五行这样……?
-
numFactor
/** * * * * */ // 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 numFactor = (num: number): number => const expression = [1, 3, 4]; let sum = 0; if (num === 0) return 1; if (num < 0) return 0; for (const exp of expression) sum += numFactor(num - exp); return sum; ; console.log(numFactor(4)); console.log(numFactor(5));
-
houseRobber
/** * * * * */ // 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 houseRobber = (houses: number[]): number => if (houses.length === 1) return houses[0]; if (houses.length === 2) return Math.max(...houses); let sum = 0; sum += Math.max( houses[0] + houseRobber(houses.slice(2)), houseRobber(houses.slice(1)) ); return sum; ; console.log(houseRobber([6, 7, 1, 30, 8, 2, 4]));
-
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:])) const convertString = (s1: string, s2: string): number => if ((!s1.length && s2.length) || (s1.length && !s2.length)) return Math.abs(s2.length - s1.length); if (s1.length === 1 && s2.length === 1) return s1 === s2 ? 0 : 1; if (s1[0] === s2[0]) return convertString(s1.substring(1), s2.substring(1)); const deleteOp = 1 + convertString(s1, s2.substring(1)), insertOp = 1 + convertString(s1.substring(1), s2), replaceOp = 1 + convertString(s1.substring(1), s2.substring(1)); return Math.min(insertOp, deleteOp, replaceOp); ; console.log(convertString('', 'abc')); console.log(convertString('abc', '')); console.log(convertString('catch', 'carch')); console.log(convertString('table', 'tbres'));
-
zero one knapsack problem
LC 有原题,但是忘了名字是啥……如果 profit 可以分的话这道题的解法用的就是贪心。
/** * * * * */ // 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 zeroOneKnapsackProblem = ( profifts: number[], weights: number[], capacity: number ) => if (capacity <= 0) return 0; if (profifts.length === 1) if (weights[0] > capacity) return 0; return profifts[0]; let takenProfit = 0, takenCapacity = 0; if (capacity > weights[0]) takenCapacity = capacity - weights[0]; takenProfit += profifts[0]; return Math.max( zeroOneKnapsackProblem(profifts.slice(1), weights.slice(1), capacity), takenProfit + zeroOneKnapsackProblem( profifts.slice(1), weights.slice(1), takenCapacity ) ); ; console.log(zeroOneKnapsackProblem([31, 26, 17, 72], [3, 1, 2, 5], 7));
-
longest common subsequence
/** * * * * */ // longest common subsequence // problem // s1 and s2 are string // find longest common subsequence which is common to both strings // subsequence - a sequence that can be driven from another sequence by deleting some elements // without changing the order of them // ex: "elephant", "erepat", res = "eepat" const longestCommonSubsequence = (s1: string, s2: string): string => if ((!s1.length && s2.length) || (s1.length && !s2.length)) return ''; if (s1.length === 1 && s2.length === 1) if (s1 === s2) return s1 === s2 ? s1 : ''; if (s1[0] === s2[0]) return ( s1[0] + longestCommonSubsequence(s1.substring(1), s2.substring(1)) ); const deleteS1 = longestCommonSubsequence(s1.substring(1), s2); const deleteS2 = longestCommonSubsequence(s1, s2.substring(1)); if (deleteS1.length > deleteS2.length) return deleteS1; return deleteS2; ; console.log(longestCommonSubsequence('elephant', 'erepat')); console.log(longestCommonSubsequence('elephant', 'erepatadadfasd'));
另一种解法,就返回 LCS 的长度而不是 LCS,本质上没啥区别
/** * * * * */ const findLCS = (s1: string, s2: string): number => if ((!s1.length && s2.length) || (s1.length && !s2.length)) return 0; if (s1.length === 1 && s2.length === 1) return s1 === s2 ? 1 : 0; if (s1[0] === s2[0]) return 1 + findLCS(s1.substring(1), s2.substring(1)); return Math.max( findLCS(s1.substring(1), s2.substring(0)), findLCS(s1.substring(0), s2.substring(1)) ); ; console.log(findLCS('elephant', 'erepat'));
-
longest palindrome subsquence
/** * * * * */ // longest palindrome subsquence // problem // s is given string // find longest palindrome subsequence // subsequence - a sequence that can be driven from another sequence by deleting some elements // without changing the order of them // ex: "elrmenmet", res = "ememe" or "emnme", length 5 const findLPS = (s: string): string => if (s.length === 1) return s; if (s.length === 2) if (s[0] === s[1]) return s; return s[0]; if (s[0] === s[s.length - 1]) return s[0] + findLPS(s.substring(1, s.length - 1)) + s[s.length - 1]; const deleteS1 = findLPS(s.substring(1)); const deleteS2 = findLPS(s.substring(0, s.length - 1)); if (deleteS1.length > deleteS2.length) return deleteS1; return deleteS2; ; console.log(findLPS('elrmenmet'));
-
minimum cost to reach the last cell
应该就是 Manhattan Tourist Problem 的简化版,毕竟 Manhattan Tourist Problem 的移动方向更多来着
/** * * * * */ // minimum cost to reach the last cell // problem // - 2d Matrix is given // - each cell has a cost associated with it for accessing // - need to start from (0, 0) and reaches (n - 1, n - 1) // - only righ or down from current cell // - find the way in which the cost is minimum // ex: // [[4, 7, 8, 6, 4] // [6, 7, 3, 9, 2] // [3, 8, 1, 2, 4] // [7, 1, 7, 3, 7] // [2, 9, 8, 9, 3]] // res: 36, 4 --> 6 --> 7 --> 3 --> 1 --> 2 --> 3 --> 7 --> 3 // min(currCost + f(down), currCost + f(right)) const minCostToReachLastCell = (matrix: number[][]): number => const recursiveCall = (i: number, j: number): number => if (i === matrix.length - 1 && j === matrix[0].length - 1) return matrix[i][j]; if (i === matrix.length || j === matrix[0].length) return Infinity; const moveRight = recursiveCall(i, j + 1), moveDown = recursiveCall(i + 1, j); return matrix[i][j] + Math.min(moveRight, moveDown); ; return recursiveCall(0, 0); ; console.log( minCostToReachLastCell([ [4, 7, 8, 6, 4], [6, 7, 3, 9, 2], [3, 8, 1, 2, 4], [7, 1, 7, 3, 7], [2, 9, 8, 9, 3], ]) );
-
number of paths to reach the last cell with given cost
和上一题解法差不多,换汤不换药
/** * * * * */ // problem // - 2D matrix is given // - Each cell has a cost associated with it for accessing // - start from (0, 0) and reaches (n - 1, n - 1) // - can only move right or down // - total cost to reach last cell is given // - find # of paths to reach the end of matrix with given cost // ex: // matrix = [ // [4, 7, 1, 6], // [5, 7, 3, 9], // [3, 2, 1, 2], // [7, 1, 6, 3], // ] // totalCost = 25 // res = 2: // - 4 --> 7 --> 1 --> 3 --> 1 --> 6 --> 3 // - 4 --> 4 --> 7 --> 3 --> 1 --> 2 --> 3 const numOfWaysToReachEnd = (matrix: number[][], cost: number): number => const recursiveCall = ( i: number, j: number, totalCost: number ): number => if (totalCost < 0) return 0; if (i === matrix.length - 1 && j === matrix[0].length - 1) if (totalCost === 0) return 1; return 0; if (i === matrix.length || j === matrix[0].length) return 0; return ( recursiveCall(i + 1, j, totalCost - matrix[i][j]) + recursiveCall(i, j + 1, totalCost - matrix[i][j]) ); ; return recursiveCall(0, 0, cost); ; console.log( numOfWaysToReachEnd( [ [4, 7, 1, 6], [5, 7, 3, 9], [3, 2, 1, 2], [7, 1, 6, 3], ], 25 ) );
以上是关于一些分治的练习题的主要内容,如果未能解决你的问题,请参考以下文章