diff --git a/README.md b/README.md index 9a76f49..5c08aea 100644 --- a/README.md +++ b/README.md @@ -117,10 +117,12 @@ ### 贪心算法 1. [返回k次交换后最大的序列](https://github.com/dengshasha/algorithm-study/blob/master/greedy/largestPermutation.js) || [Geeks地址](https://www.geeksforgeeks.org/largest-permutation-k-swaps/) +2. ### 找不到分类 1. [实现一个最近最少使用的缓存结构](https://github.com/dengshasha/algorithm-study/blob/master/others/LRUCache.js) || [leetcode地址](https://leetcode.com/problems/lru-cache/) 2. [设计一个不包含重复数据,可以插入,删除,随机获取值的类](https://github.com/dengshasha/algorithm-study/blob/master/others/randomizedSet.js) || [leetcode地址](https://leetcode.com/problems/insert-delete-getrandom-o1/) 3. [设计一个将嵌套数组转换为扁平化数组的类](https://github.com/dengshasha/algorithm-study/blob/master/others/flattenNestedListIterator.js) || [leetcode地址](https://leetcode.com/problems/flatten-nested-list-iterator/) +4. [计算n!的末尾0的个数](https://github.com/dengshasha/algorithm-study/blob/master/others/factorialTrailingZeroes.js) || [leetcode地址](https://leetcode.com/problems/factorial-trailing-zeroes/) ### 分治法 1. [Merge k Sorted Lists](https://github.com/dengshasha/algorithm-study/blob/master/mergeKSortedLists.js) diff --git a/dynamicProgramming/climbStairs.js b/dynamicProgramming/climbStairs.js index 6f3920d..81a0eae 100644 --- a/dynamicProgramming/climbStairs.js +++ b/dynamicProgramming/climbStairs.js @@ -5,7 +5,24 @@ * @param {number} n * @return {number} * leetcode address: https://leetcode.com/problems/climbing-stairs/ + * 1. edge case: + * n = 1, there is only 1 way to climb to the top + * n = 2, there are 2 ways to climb to the top, climb 1 step each time as twice or climb 2 steps. + * 2. state transition equation: + * dp[i] = dp[i-2] + dp[i-1] (i >= 3) */ +var climbStairs_dfs = function(n) { + + let dp = [] + function recursive(k) { + + if(k < 0) return 0; + if(k === 0) return 1; + if(dp[k] !== undefined) return dp[k] + return dp[k] = recursive(k-1) + recursive(k-2) + } + return recursive(n) +} var climbStairs = function(n) { let dp = [0,1,2] if(n <= 2) return dp[n] @@ -15,4 +32,4 @@ var climbStairs = function(n) { return dp[n] }; -console.log(climbStairs(44)) \ No newline at end of file +console.log(climbStairs_dfs(4)) \ No newline at end of file diff --git a/dynamicProgramming/decodeWays.js b/dynamicProgramming/decodeWays.js new file mode 100644 index 0000000..d3fb643 --- /dev/null +++ b/dynamicProgramming/decodeWays.js @@ -0,0 +1,52 @@ +/** + * Created by dengxuelian on 2023/03/24 + * leetcode link: https://leetcode.com/problems/decode-ways/description/ + */ + +/** + * @param {string} s + * @return {number} + * 先不考虑 < 1和 >26是不合法的情况来推导通用公式 + * s=‘1‘, way[1] = 1 + * s=’12‘, 组合情况是(1,2) 和(12) way[2] = 2 + * s=’123‘, 组合情况是(1,2,3), (12,3) 和(1, 23) way[3] = 3 + * 观察这个规律可以得出way[i] = way[i-1] + way[i-2] + * 在这些组合情况中,需要排除一些不合法的组合情况 + * 情况一:s='0*'s是0开头的任意长度的数字,way=0 + * 情况二:当前位置的数字是0,且前一个位置也是0,或者是大于2,比如s='100', s='130', 则也不能组成字母,way=0 + * 情况三:当前位置的数字是0,且前一个位置的数字是1或者2,比如s='120', 那么当前位置必须要绑定前一个位置的数字组成字母,此时必须要牺牲前一个位置和当前位置的可能性, + * 那么i位置的组合方式=i-2位置的组合方式(重点理解!!!!因为i-1位置已经被固定使用了) + * 情况四:当前位置非0,前一个位置是0,则当前位置加入后不会增加组合的可能性,则组合方式不变,way[i] = way[i-1] + * 情况五:当前+前一个位置大于26,则和情况四一样,way[i] = way[i-1] + */ +var numDecodings = function(s) { + // 0开头的字符是不合法的情况 + if(s[0] === '0') return 0; + let dp = [] + // 初始状态,排除了0开头以后,如果s.length=1, 则仅有一个字母。 + dp[0] = 1, dp[1] = 1 + + for(let i = 1; i < s.length; i++) { + // 当前字符为0,有两种情况导致整个字符串无法形成合法的字母组合 + // 1. 前一个数字>2 + // 2. 前一个数字是0 + if(s[i] === '0' && (s[i-1] > 2 || s[i-1] === '0')) { + return 0; + } + if(s[i] === '0') { + //当前字符为0,但是可以和前一个数字组成一个字母,意味着前一个数字必须和当前数字一起使用,则前一个数字位置的 + //可能性不需要考虑,此时当前位置的组成方式=前2个位置的组成方式 + dp[i+1] = dp[i-1] + } else if(s[i-1] === '0' || s[i-1]+s[i] > 26) { + //前一个字符为0,当前数字加入后不会增加可能性,所以等于前一个位置的组成方式 + //当前+前一个数字超出了最大值后,当前数字加入后也不会增加可能性 + dp[i+1] = dp[i] + } else { + //通用方程 + dp[i+1] = dp[i] + dp[i-1] + } + } + return dp[s.length] +}; + +console.log(numDecodings('27')) \ No newline at end of file diff --git a/index.html b/index.html index cfea61f..1fdcc73 100644 --- a/index.html +++ b/index.html @@ -6,6 +6,6 @@ Document - + \ No newline at end of file diff --git a/others/factorialTrailingZeroes.js b/others/factorialTrailingZeroes.js new file mode 100644 index 0000000..b1c9530 --- /dev/null +++ b/others/factorialTrailingZeroes.js @@ -0,0 +1,19 @@ +/** + * Created by dengxuelian on 2022/11/20 + */ +/** + * @param {number} n + * @return {number} + * Trailing 0s in n! = Count of 5s in prime factors of n! + * = floor(n/5) + floor(n/25) + floor(n/125) + .... + */ +var trailingZeroes = function(n) { + let zero = 0 + let div = 5 + while (Math.floor(n / div) !== 0 ) { + zero += Math.floor(n/div) + div *= 5 + } + + return zero; +}; \ No newline at end of file diff --git a/string/climbStairs.js b/string/climbStairs.js deleted file mode 100644 index 6c3a2a2..0000000 --- a/string/climbStairs.js +++ /dev/null @@ -1,28 +0,0 @@ -/** - * @param {number} n - * @return {number} - * leetcode address: https://leetcode.com/problems/climbing-stairs/ - */ -var climbStairs = function(n) { - let way = 0; - let memo = {} - recursive(n, n) - function recursive(target, n) { - if(n < 0) return; - if(n === 0) { - way++; - memo[target] = way; - return; - } - if(memo[n]) { - way += memo[n] - memo[target] = way; - return; - } - recursive(n, n-1) - recursive(n, n-2) - } - return way -}; - -console.log(climbStairs(7)) \ No newline at end of file diff --git a/string/generateParenthesis.js b/string/generateParenthesis.js new file mode 100644 index 0000000..16501ce --- /dev/null +++ b/string/generateParenthesis.js @@ -0,0 +1,28 @@ +/** + * Created by dengxuelian on 2023/3/1 + */ +/** + * @param {number} n + * @return {string[]} + */ +var generateParenthesis = function(n) { + const pareLen = n * 2; + let res = [] + + function recursive(i, pareStr, leftTotal, rightTotal) { + if(i === pareLen-1) { + res.push(pareStr) + return; + } + + if(leftTotal < n) { + recursive(i+1, pareStr+'(', leftTotal+1, rightTotal) + } + if(rightTotal < leftTotal) { + recursive(i+1, pareStr+')', leftTotal, rightTotal+1) + } + + } + recursive(0, '(', 1, 0) + return res +}; \ No newline at end of file diff --git a/string/letterCombOfPhoneNum.js b/string/letterCombOfPhoneNum.js index 2eb9a1e..93d7798 100644 --- a/string/letterCombOfPhoneNum.js +++ b/string/letterCombOfPhoneNum.js @@ -1,3 +1,6 @@ +/** + * Created by dengxuelian on 2022/3/5 + */ /** * @param {string} digits * @return {string[]} @@ -38,4 +41,41 @@ var letterCombinations = function(digits) { return ans; }; -console.log(letterCombinations('234')) \ No newline at end of file +console.log(letterCombinations('234')) + + +/** + * 2023/3/1 + * @param {string} digits + * @return {string[]} + */ + +const maps = { + 2: 'abc', + 3: 'def', + 4: 'ghi', + 5: 'jkl', + 6: 'mno', + 7: 'pqrs', + 8: 'tuv', + 9: 'wxyz' +} +var letterCombinations = function(digits) { + let res = [] + let alphaArr = [] + for(let i = 0; i < digits.length; i++) { + alphaArr.push(maps[digits[i]]) + } + // alphaArr = ['abc', 'def'] + function recursive(i, str) { + if(i === alphaArr.length) { + str.length && res.push(str) + return; + } + for(let j=0; j < alphaArr[i].length; j++) { + recursive(i+1, str.concat(alphaArr[i][j])) + } + } + recursive(0, '') + return res; +}; \ No newline at end of file