diff --git a/39.combination-sum.js b/39.combination-sum.js new file mode 100644 index 000000000..2c6694259 --- /dev/null +++ b/39.combination-sum.js @@ -0,0 +1,70 @@ +/* + * @lc app=leetcode id=39 lang=javascript + * + * [39] Combination Sum + * + * https://leetcode.com/problems/combination-sum/description/ + * + * algorithms + * Medium (46.89%) + * Total Accepted: 326.7K + * Total Submissions: 684.2K + * Testcase Example: '[2,3,6,7]\n7' + * + * Given a set of candidate numbers (candidates) (without duplicates) and a + * target number (target), find all unique combinations in candidates where the + * candidate numbers sums to target. + * + * The same repeated number may be chosen from candidates unlimited number of + * times. + * + * Note: + * + * + * All numbers (including target) will be positive integers. + * The solution set must not contain duplicate combinations. + * + * + * Example 1: + * + * + * Input: candidates = [2,3,6,7], target = 7, + * A solution set is: + * [ + * ⁠ [7], + * ⁠ [2,2,3] + * ] + * + * + * Example 2: + * + * + * Input: candidates = [2,3,5], target = 8, + * A solution set is: + * [ + * [2,2,2,2], + * [2,3,3], + * [3,5] + * ] + * + */ + +function backtrack(list, tempList, nums, remain, start) { + if (remain < 0) return; + else if (remain === 0) return list.push([...tempList]); + for (let i = start; i < nums.length; i++) { + tempList.push(nums[i]); + backtrack(list, tempList, nums, remain - nums[i], i); // 数字可以重复使用, i + 1代表不可以重复利用 + tempList.pop(); + } +} +/** + * @param {number[]} candidates + * @param {number} target + * @return {number[][]} + */ +var combinationSum = function(candidates, target) { + const list = []; + backtrack(list, [], candidates.sort((a, b) => a - b), target, 0); + return list; +}; diff --git a/40.combination-sum-ii.js b/40.combination-sum-ii.js new file mode 100644 index 000000000..df1c65ece --- /dev/null +++ b/40.combination-sum-ii.js @@ -0,0 +1,71 @@ +/* + * @lc app=leetcode id=40 lang=javascript + * + * [40] Combination Sum II + * + * https://leetcode.com/problems/combination-sum-ii/description/ + * + * algorithms + * Medium (40.31%) + * Total Accepted: 212.8K + * Total Submissions: 519K + * Testcase Example: '[10,1,2,7,6,1,5]\n8' + * + * Given a collection of candidate numbers (candidates) and a target number + * (target), find all unique combinations in candidates where the candidate + * numbers sums to target. + * + * Each number in candidates may only be used once in the combination. + * + * Note: + * + * + * All numbers (including target) will be positive integers. + * The solution set must not contain duplicate combinations. + * + * + * Example 1: + * + * + * Input: candidates = [10,1,2,7,6,1,5], target = 8, + * A solution set is: + * [ + * ⁠ [1, 7], + * ⁠ [1, 2, 5], + * ⁠ [2, 6], + * ⁠ [1, 1, 6] + * ] + * + * + * Example 2: + * + * + * Input: candidates = [2,5,2,1,2], target = 5, + * A solution set is: + * [ + * [1,2,2], + * [5] + * ] + * + * + */ +function backtrack(list, tempList, nums, remain, start) { + if (remain < 0) return; + else if (remain === 0) return list.push([...tempList]); + for (let i = start; i < nums.length; i++) { + if(i > start && nums[i] == nums[i-1]) continue; // skip duplicates + tempList.push(nums[i]); + backtrack(list, tempList, nums, remain - nums[i], i + 1); // i + 1代表不可以重复利用, i 代表数字可以重复使用 + tempList.pop(); + } + } +/** + * @param {number[]} candidates + * @param {number} target + * @return {number[][]} + */ +var combinationSum2 = function(candidates, target) { + const list = []; + backtrack(list, [], candidates.sort((a, b) => a - b), target, 0); + return list; +}; diff --git a/46.permutations.js b/46.permutations.js new file mode 100644 index 000000000..474e393f0 --- /dev/null +++ b/46.permutations.js @@ -0,0 +1,50 @@ +/* + * @lc app=leetcode id=46 lang=javascript + * + * [46] Permutations + * + * https://leetcode.com/problems/permutations/description/ + * + * algorithms + * Medium (53.60%) + * Total Accepted: 344.6K + * Total Submissions: 642.9K + * Testcase Example: '[1,2,3]' + * + * Given a collection of distinct integers, return all possible permutations. + * + * Example: + * + * + * Input: [1,2,3] + * Output: + * [ + * ⁠ [1,2,3], + * ⁠ [1,3,2], + * ⁠ [2,1,3], + * ⁠ [2,3,1], + * ⁠ [3,1,2], + * ⁠ [3,2,1] + * ] + * + * + */ +function backtrack(list, tempList, nums) { + if (tempList.length === nums.length) return list.push([...tempList]); + for(let i = 0; i < nums.length; i++) { + if (tempList.includes(nums[i])) continue; + tempList.push(nums[i]); + backtrack(list, tempList, nums); + tempList.pop(); + } +} +/** + * @param {number[]} nums + * @return {number[][]} + */ +var permute = function(nums) { + const list = []; + backtrack(list, [], nums) + return list +}; + diff --git a/47.permutations-ii.js b/47.permutations-ii.js new file mode 100644 index 000000000..abeeb183c --- /dev/null +++ b/47.permutations-ii.js @@ -0,0 +1,52 @@ +/* + * @lc app=leetcode id=47 lang=javascript + * + * [47] Permutations II + * + * https://leetcode.com/problems/permutations-ii/description/ + * + * algorithms + * Medium (39.29%) + * Total Accepted: 234.1K + * Total Submissions: 586.2K + * Testcase Example: '[1,1,2]' + * + * Given a collection of numbers that might contain duplicates, return all + * possible unique permutations. + * + * Example: + * + * + * Input: [1,1,2] + * Output: + * [ + * ⁠ [1,1,2], + * ⁠ [1,2,1], + * ⁠ [2,1,1] + * ] + * + * + */ +function backtrack(list, nums, tempList, visited) { + if (tempList.length === nums.length) return list.push([...tempList]); + for (let i = 0; i < nums.length; i++) { + if (visited[i]) continue; + // visited[i - 1] 容易忽略 + if (i > 0 && nums[i] === nums[i - 1] && visited[i - 1]) continue; + + visited[i] = true; + tempList.push(nums[i]); + backtrack(list, nums, tempList, visited); + visited[i] = false; + tempList.pop(); + } +} +/** + * @param {number[]} nums + * @return {number[][]} + */ +var permuteUnique = function(nums) { + const list = []; + backtrack(list, nums.sort((a, b) => a - b), [], []); + return list; +}; diff --git a/62.unique-paths.js b/62.unique-paths.js new file mode 100644 index 000000000..478931986 --- /dev/null +++ b/62.unique-paths.js @@ -0,0 +1,71 @@ +/* + * @lc app=leetcode id=62 lang=javascript + * + * [62] Unique Paths + * + * https://leetcode.com/problems/unique-paths/description/ + * + * algorithms + * Medium (46.53%) + * Total Accepted: 277K + * Total Submissions: 587.7K + * Testcase Example: '3\n2' + * + * A robot is located at the top-left corner of a m x n grid (marked 'Start' in + * the diagram below). + * + * The robot can only move either down or right at any point in time. The robot + * is trying to reach the bottom-right corner of the grid (marked 'Finish' in + * the diagram below). + * + * How many possible unique paths are there? + * + * + * Above is a 7 x 3 grid. How many possible unique paths are there? + * + * Note: m and n will be at most 100. + * + * Example 1: + * + * + * Input: m = 3, n = 2 + * Output: 3 + * Explanation: + * From the top-left corner, there are a total of 3 ways to reach the + * bottom-right corner: + * 1. Right -> Right -> Down + * 2. Right -> Down -> Right + * 3. Down -> Right -> Right + * + * + * Example 2: + * + * + * Input: m = 7, n = 3 + * Output: 28 + * + * START + */ +/** + * @param {number} m + * @param {number} n + * @return {number} + */ +var uniquePaths = function(m, n) { + // backtracking + const dp = []; + for (let i = 0; i < m + 1; i++) { + dp[i] = []; + dp[i][0] = 0; + } + for (let i = 0; i < n + 1; i++) { + dp[0][i] = 0; + } + for (let i = 1; i < m + 1; i++) { + for(let j = 1; j < n + 1; j++) { + dp[i][j] = j === 1 ? 1 : dp[i - 1][j] + dp[i][j - 1]; + } + } + + return dp[m][n]; +}; diff --git a/78.subsets.js b/78.subsets.js new file mode 100644 index 000000000..9c0830ac7 --- /dev/null +++ b/78.subsets.js @@ -0,0 +1,53 @@ +/* + * @lc app=leetcode id=78 lang=javascript + * + * [78] Subsets + * + * https://leetcode.com/problems/subsets/description/ + * + * algorithms + * Medium (51.19%) + * Total Accepted: 351.6K + * Total Submissions: 674.8K + * Testcase Example: '[1,2,3]' + * + * Given a set of distinct integers, nums, return all possible subsets (the + * power set). + * + * Note: The solution set must not contain duplicate subsets. + * + * Example: + * + * + * Input: nums = [1,2,3] + * Output: + * [ + * ⁠ [3], + * [1], + * [2], + * [1,2,3], + * [1,3], + * [2,3], + * [1,2], + * [] + * ] + * + */ +function backtrack(list, tempList, nums, start) { + list.push([...tempList]); + for(let i = start; i < nums.length; i++) { + tempList.push(nums[i]); + backtrack(list, tempList, nums, i + 1); + tempList.pop(); + } +} +/** + * @param {number[]} nums + * @return {number[][]} + */ +var subsets = function(nums) { + const list = []; + backtrack(list, [], nums, 0); + return list; +}; + diff --git a/90.subsets-ii.js b/90.subsets-ii.js new file mode 100644 index 000000000..a54c675a2 --- /dev/null +++ b/90.subsets-ii.js @@ -0,0 +1,53 @@ +/* + * @lc app=leetcode id=90 lang=javascript + * + * [90] Subsets II + * + * https://leetcode.com/problems/subsets-ii/description/ + * + * algorithms + * Medium (41.53%) + * Total Accepted: 197.1K + * Total Submissions: 469.1K + * Testcase Example: '[1,2,2]' + * + * Given a collection of integers that might contain duplicates, nums, return + * all possible subsets (the power set). + * + * Note: The solution set must not contain duplicate subsets. + * + * Example: + * + * + * Input: [1,2,2] + * Output: + * [ + * ⁠ [2], + * ⁠ [1], + * ⁠ [1,2,2], + * ⁠ [2,2], + * ⁠ [1,2], + * ⁠ [] + * ] + * + * + */ +function backtrack(list, tempList, nums, start) { + list.push([...tempList]); + for(let i = start; i < nums.length; i++) { + if (i > start && nums[i] === nums[i - 1]) continue; + tempList.push(nums[i]); + backtrack(list, tempList, nums, i + 1) + tempList.pop(); + } +} +/** + * @param {number[]} nums + * @return {number[][]} + */ +var subsetsWithDup = function(nums) { + const list = []; + backtrack(list, [], nums.sort((a, b) => a - b), 0, []) + return list; +}; + diff --git a/README.md b/README.md index ea0303c23..ae04c02cc 100644 --- a/README.md +++ b/README.md @@ -53,9 +53,9 @@ leetcode 题解,记录自己的 leetcode 解题之路。 ## 精彩预告 -301. remove-invalid-parentheses: +42.trapping-rain-water-1(雨水收集问题): -![remove-invalid-parentheses](./assets/problems/301.remove-invalid-parentheses.png) +![42.trapping-rain-water](./assets/problems/42.trapping-rain-water-1.png) 浏览器中的栈: @@ -98,6 +98,7 @@ leetcode 题解,记录自己的 leetcode 解题之路。 - [11.container-with-most-water](./problems/11.container-with-most-water.md) - [19. Remove Nth Node From End of List](./problems/removeNthNodeFromEndofList.md) - [24. Swap Nodes In Pairs](./problems/swapNodesInPairs.md) +- [55.jump-game.md](./problems/55.jump-game.md.md) - [75.sort-colors.md](./problems/75.sort-colors.md) - [86.partition-list](./problems/86.partition-list.md) - [92.reverse-linked-list-ii](./problems/92.reverse-linked-list-ii.md) @@ -109,6 +110,7 @@ leetcode 题解,记录自己的 leetcode 解题之路。 - [150.evaluate-reverse-polish-notation](./problems/150.evaluate-reverse-polish-notation.md) - [199.binary-tree-right-side-view](./problems/199.binary-tree-right-side-view.md) - [201.bitwise-and-of-numbers-range](./problems/201.bitwise-and-of-numbers-range.md) +- [208.implement-trie-prefix-tree](./problems/208.implement-trie-prefix-tree.md) - [209.minimum-size-subarray-sum](./problems/209.minimum-size-subarray-sum.md) - 🆕 [240.search-a-2-d-matrix-ii](./problems/240.search-a-2-d-matrix-ii.md) - [279.perfect-squares](./problems/279.perfect-squares.md) @@ -123,7 +125,8 @@ leetcode 题解,记录自己的 leetcode 解题之路。 - [900.rle-iterator](./problems/900.rle-iterator.md) #### 困难难度 - +- [42.trapping-rain-water](./problems/42.trapping-rain-water.md) +- [128.longest-consecutive-sequence](./problems/128.longest-consecutive-sequence.md) - [145.binary-tree-postorder-traversal](./problems/145.binary-tree-postorder-traversal.md) - [146.lru-cache](./problems/146.lru-cache.md) - 🆕 [295.find-median-from-data-stream.md](./problems/295.find-median-from-data-stream.md) @@ -151,9 +154,13 @@ anki - 文件 - 导入 - 下拉格式选择“打包的 anki集合”,然后 ### 计划 -- [494.target-sum] +- [494.target-sum](./todo/494.target-sum.js) + +- [609.find-duplicate-file-in-system](./todo/609.find-duplicate-file-in-system.js) + +- [10.regular-expression-matching](./todo/10.regular-expression-matching.js) -- [609.find-duplicate-file-in-system] +- [365.water-and-jug-problem](./todo/365.water-and-jug-problem.js) - anki 卡片 完善 @@ -165,6 +172,6 @@ anki - 文件 - 导入 - 下拉格式选择“打包的 anki集合”,然后 (qq 群) -![wechat-group-chat](./assets/wechat-group-chat.png) +![wechat-group-chat](./assets/wechat-group-chat.jpg) (微信群, 由于微信的限制,只可以七天之内才能加入) diff --git a/assets/problems/208.implement-trie-prefix-tree-1.png b/assets/problems/208.implement-trie-prefix-tree-1.png new file mode 100644 index 000000000..573565a2e Binary files /dev/null and b/assets/problems/208.implement-trie-prefix-tree-1.png differ diff --git a/assets/problems/42.trapping-rain-water-1.png b/assets/problems/42.trapping-rain-water-1.png new file mode 100644 index 000000000..578e81ebe Binary files /dev/null and b/assets/problems/42.trapping-rain-water-1.png differ diff --git a/assets/wechat-group-chat.jpg b/assets/wechat-group-chat.jpg new file mode 100644 index 000000000..5f39b878d Binary files /dev/null and b/assets/wechat-group-chat.jpg differ diff --git a/assets/wechat-group-chat.png b/assets/wechat-group-chat.png deleted file mode 100644 index 59fc5a01c..000000000 Binary files a/assets/wechat-group-chat.png and /dev/null differ diff --git a/problems/128.longest-consecutive-sequence.md b/problems/128.longest-consecutive-sequence.md new file mode 100644 index 000000000..680a3a86b --- /dev/null +++ b/problems/128.longest-consecutive-sequence.md @@ -0,0 +1,115 @@ +## 题目地址 + +https://leetcode.com/problems/longest-consecutive-sequence/description/ + +## 题目描述 + +``` +Given an unsorted array of integers, find the length of the longest consecutive elements sequence. + +Your algorithm should run in O(n) complexity. + +Example: + +Input: [100, 4, 200, 1, 3, 2] +Output: 4 +Explanation: The longest consecutive elements sequence is [1, 2, 3, 4]. Therefore its length is 4. +Accepted +200,786 +Submissions +485,346 + +``` + +## 思路 + +这是一道最最长连续数字序列长度的题目, 官网给出的难度是`hard`. + +符合直觉的做法是先排序,然后用一个变量记录最大值,遍历去更新最大值即可, + +代码: + +```js +if (nums.length === 0) return 0; +let count = 1; +let maxCount = 1; +// 这里其实可以不需要排序,这么做只不过是为了方便理解 +nums = [...new Set(nums)].sort((a, b) => a - b); +for (let i = 0; i < nums.length - 1; i++) { + if (nums[i + 1] - nums[i] === 1) { + count++; + } else { + if (count > maxCount) { + maxCount = count; + } + count = 1; + } +} +return Math.max(count, maxCount); +``` + +但是需要排序时间复杂度会上升,题目要求时间复杂度为 O(n), +那么我们其实可以不用排序去解决的。 + +思路就是将之前”排序之后,通过比较前后元素是否相差 1 来判断是否连续“的思路改为 +不排序而是`直接遍历,然后在内部循环里面查找是否存在当前值的邻居元素`,但是马上有一个 +问题,内部我们`查找是否存在当前值的邻居元素`的过程如果使用数组时间复杂度是 O(n), +那么总体的复杂度就是 O(n^2),完全不可以接受。怎么办呢? + +我们换个思路,用空间来换时间。比如用类似于 hashmap 这样的数据结构优化查询部分,将时间复杂度降低到 O(1), 代码见后面`代码部分` + +## 关键点解析 + +- 空间换时间 + +## 代码 + +```js +/* + * @lc app=leetcode id=128 lang=javascript + * + * [128] Longest Consecutive Sequence + * + * https://leetcode.com/problems/longest-consecutive-sequence/description/ + * + * algorithms + * Hard (40.98%) + * Total Accepted: 200.3K + * Total Submissions: 484.5K + * Testcase Example: '[100,4,200,1,3,2]' + * + * Given an unsorted array of integers, find the length of the longest + * consecutive elements sequence. + * + * Your algorithm should run in O(n) complexity. + * + * Example: + * + * + * Input: [100, 4, 200, 1, 3, 2] + * Output: 4 + * Explanation: The longest consecutive elements sequence is [1, 2, 3, 4]. + * Therefore its length is 4. + * + * + */ +/** + * @param {number[]} nums + * @return {number} + */ +var longestConsecutive = function(nums) { + nums = new Set(nums); + let max = 0; + let y = 0; + nums.forEach(x => { + if (!nums.has(x - 1)) { + y = x + 1; + while (nums.has(y)) { + y = y + 1; + } + max = Math.max(max, y - x); // y - x 就是从i开始到最后有多少连续的数字 + } + }); + return max; +}; +``` diff --git a/problems/208.implement-trie-prefix-tree.md b/problems/208.implement-trie-prefix-tree.md new file mode 100644 index 000000000..624ed3456 --- /dev/null +++ b/problems/208.implement-trie-prefix-tree.md @@ -0,0 +1,189 @@ +## 题目地址 + +https://leetcode.com/problems/implement-trie-prefix-tree/description/ + +## 题目描述 + +``` +Implement a trie with insert, search, and startsWith methods. + +Example: + +Trie trie = new Trie(); + +trie.insert("apple"); +trie.search("apple"); // returns true +trie.search("app"); // returns false +trie.startsWith("app"); // returns true +trie.insert("app"); +trie.search("app"); // returns true +Note: + +You may assume that all inputs are consist of lowercase letters a-z. +All inputs are guaranteed to be non-empty strings. + +``` + +## 思路 + +这是一道很直接的题目,上来就让你实现`前缀树(字典树)`。这算是基础数据结构中的 +知识了,不清楚什么是字典树的可以查阅相关资料。 + +我们看到题目给出的使用方法`new Trie`, `insert`,`search`和`startWith`. + +为了区分`search`和`startWith`我们需要增加一个标示来区分当前节点是否是某个单词的结尾。 +因此节点的数据结构应该是: + +```js +function TrieNode(val) { + this.val = val; // 当前的字母 + this.children = []; // 题目要求字典仅有a-z,那么其长度最大为26(26个字母) + this.isWord = false; +} +``` + +每次 insert 我们其实都是从根节点出发,一个一个找到我们需要添加的节点,修改 children 的值. + +我们应该修改哪一个 child 呢? 我们需要一个函数来计算索引 + +```js +function computeIndex(c) { + return c.charCodeAt(0) - "a".charCodeAt(0); +} +``` + +其实不管 insert, search 和 startWith 的逻辑都是差不多的,都是从 root 出发, +找到我们需要操作的 child, 然后进行相应操作(添加,修改,返回)。 + +![208.implement-trie-prefix-tree-1](../assets/problems/208.implement-trie-prefix-tree-1.png) + +## 关键点解析 + +- 前缀树 + +- 核心逻辑 + +```js + const c = word[i]; + const current = computeIndex(c) +if (!ws.children[current]) { + ws.children[current] = new TrieNode(c); + } + ws = ws.children[current]; // 深度递增 +} + +``` + +## 代码 + +```js +/* + * @lc app=leetcode id=208 lang=javascript + * + * [208] Implement Trie (Prefix Tree) + * + * https://leetcode.com/problems/implement-trie-prefix-tree/description/ + * + * algorithms + * Medium (36.93%) + * Total Accepted: 172K + * Total Submissions: 455.5K + * Testcase Example: '["Trie","insert","search","search","startsWith","insert","search"]\n[[],["apple"],["apple"],["app"],["app"],["app"],["app"]]' + * + * Implement a trie with insert, search, and startsWith methods. + * + * Example: + * + * + * Trie trie = new Trie(); + * + * trie.insert("apple"); + * trie.search("apple"); // returns true + * trie.search("app"); // returns false + * trie.startsWith("app"); // returns true + * trie.insert("app"); + * trie.search("app"); // returns true + * + * + * Note: + * + * + * You may assume that all inputs are consist of lowercase letters a-z. + * All inputs are guaranteed to be non-empty strings. + * + * + */ +function TrieNode(val) { + this.val = val; + this.children = []; + this.isWord = false; +} + +function computeIndex(c) { + return c.charCodeAt(0) - "a".charCodeAt(0); +} +/** + * Initialize your data structure here. + */ +var Trie = function() { + this.root = new TrieNode(null); +}; + +/** + * Inserts a word into the trie. + * @param {string} word + * @return {void} + */ +Trie.prototype.insert = function(word) { + let ws = this.root; + for (let i = 0; i < word.length; i++) { + const c = word[i]; + const current = computeIndex(c); + if (!ws.children[current]) { + ws.children[current] = new TrieNode(c); + } + ws = ws.children[current]; + } + ws.isWord = true; +}; + +/** + * Returns if the word is in the trie. + * @param {string} word + * @return {boolean} + */ +Trie.prototype.search = function(word) { + let ws = this.root; + for (let i = 0; i < word.length; i++) { + const c = word[i]; + const current = computeIndex(c); + if (!ws.children[current]) return false; + ws = ws.children[current]; + } + return ws.isWord; +}; + +/** + * Returns if there is any word in the trie that starts with the given prefix. + * @param {string} prefix + * @return {boolean} + */ +Trie.prototype.startsWith = function(prefix) { + let ws = this.root; + for (let i = 0; i < prefix.length; i++) { + const c = prefix[i]; + const current = computeIndex(c); + if (!ws.children[current]) return false; + ws = ws.children[current]; + } + return true; +}; + +/** + * Your Trie object will be instantiated and called as such: + * var obj = new Trie() + * obj.insert(word) + * var param_2 = obj.search(word) + * var param_3 = obj.startsWith(prefix) + */ +``` diff --git a/problems/42.trapping-rain-water.md b/problems/42.trapping-rain-water.md new file mode 100644 index 000000000..f7dbf1392 --- /dev/null +++ b/problems/42.trapping-rain-water.md @@ -0,0 +1,112 @@ +## 题目地址 +https://leetcode.com/problems/trapping-rain-water/description/ + +## 题目描述 + + +``` +Given n non-negative integers representing an elevation map where the width of each bar is 1, compute how much water it is able to trap after raining. + + +The above elevation map is represented by array [0,1,0,2,1,0,1,3,2,1,2,1]. In this case, 6 units of rain water (blue section) are being trapped. Thanks Marcos for contributing this image! + + +``` + +![42.trapping-rain-water-1](../assets/problems/42.trapping-rain-water-1.png) + +``` +Example: + +Input: [0,1,0,2,1,0,1,3,2,1,2,1] +Output: 6 + +``` + +## 思路 + +这是一道雨水收集的问题, 难度为`hard`. 如图所示,让我们求下过雨之后最多可以积攒多少的水。 + +如果采用暴力求解的话,思路应该是height数组依次求和,然后相加。 + +伪代码: + +```js + +for(let i = 0; i < height.length; i++) { + area += (h[i] - height[i]) * 1; // h为下雨之后的水位 +} + +``` +如上图那么h为 [1, 1, 2, 2, ,2 ,2, ,3, 2, 2, 2, 1] + +问题转化为求h,那么h[i]又等于`左右两侧柱子的最大值中的较小值`,即 +`h[i] = Math.min(左边柱子最大值, 右边柱子最大值)` + +问题的关键在于求解`左边柱子最大值`和`右边柱子最大值`, +我们其实可以用两个数组来表示`leftMax`, `rightMax`, +以leftMax为例,leftMax[i]代表i的左侧柱子的最大值,因此我们维护两个数组即可。 +## 关键点解析 + +- 建模 `h[i] = Math.min(左边柱子最大值, 右边柱子最大值)`(h为下雨之后的水位) + +## 代码 + +```js + +/* + * @lc app=leetcode id=42 lang=javascript + * + * [42] Trapping Rain Water + * + * https://leetcode.com/problems/trapping-rain-water/description/ + * + * algorithms + * Hard (42.06%) + * Total Accepted: 278.1K + * Total Submissions: 651.6K + * Testcase Example: '[0,1,0,2,1,0,1,3,2,1,2,1]' + * + * Given n non-negative integers representing an elevation map where the width + * of each bar is 1, compute how much water it is able to trap after raining. + * + * + * The above elevation map is represented by array [0,1,0,2,1,0,1,3,2,1,2,1]. + * In this case, 6 units of rain water (blue section) are being trapped. Thanks + * Marcos for contributing this image! + * + * Example: + * + * + * Input: [0,1,0,2,1,0,1,3,2,1,2,1] + * Output: 6 + * + */ +/** + * @param {number[]} height + * @return {number} + */ +var trap = function(height) { + let max = 0; + let volumn = 0; + const leftMax = []; + const rightMax = []; + + for(let i = 0; i < height.length; i++) { + leftMax[i] = max = Math.max(height[i], max); + } + + max = 0; + + for(let i = height.length - 1; i >= 0; i--) { + rightMax[i] = max = Math.max(height[i], max); + } + + for(let i = 0; i < height.length; i++) { + volumn = volumn + Math.min(leftMax[i], rightMax[i]) - height[i] + } + + return volumn; +}; + +``` diff --git a/problems/55.jump-game.md b/problems/55.jump-game.md new file mode 100644 index 000000000..2aa239fa8 --- /dev/null +++ b/problems/55.jump-game.md @@ -0,0 +1,96 @@ + +## 题目地址 +https://leetcode.com/problems/jump-game/description/ + +## 题目描述 +``` +Given an array of non-negative integers, you are initially positioned at the first index of the array. + +Each element in the array represents your maximum jump length at that position. + +Determine if you are able to reach the last index. + +Example 1: + +Input: [2,3,1,1,4] +Output: true +Explanation: Jump 1 step from index 0 to 1, then 3 steps to the last index. +Example 2: + +Input: [3,2,1,0,4] +Output: false +Explanation: You will always arrive at index 3 no matter what. Its maximum + jump length is 0, which makes it impossible to reach the last index. + +``` + +## 思路 + +这道题目是一道典型的`回溯`类型题目。 +思路就是用一个变量记录当前能够到达的最大的索引,我们逐个遍历数组中的元素去更新这个索引。 +变量完成判断这个索引是否大于数组下表即可。 +## 关键点解析 + +- 建模 (记录和更新当前位置能够到达的最大的索引即可) + +## 代码 + +```js + +/* + * @lc app=leetcode id=55 lang=javascript + * + * [55] Jump Game + * + * https://leetcode.com/problems/jump-game/description/ + * + * algorithms + * Medium (31.38%) + * Total Accepted: 252.4K + * Total Submissions: 797.2K + * Testcase Example: '[2,3,1,1,4]' + * + * Given an array of non-negative integers, you are initially positioned at the + * first index of the array. + * + * Each element in the array represents your maximum jump length at that + * position. + * + * Determine if you are able to reach the last index. + * + * Example 1: + * + * + * Input: [2,3,1,1,4] + * Output: true + * Explanation: Jump 1 step from index 0 to 1, then 3 steps to the last + * index. + * + * + * Example 2: + * + * + * Input: [3,2,1,0,4] + * Output: false + * Explanation: You will always arrive at index 3 no matter what. Its + * maximum + * jump length is 0, which makes it impossible to reach the last index. + * + * + */ +/** + * @param {number[]} nums + * @return {boolean} + */ +var canJump = function(nums) { + let max = 0; // 能够走到的数组下标 + + for(let i = 0; i < nums.length; i++) { + if (max < i) return false; // 当前这一步都走不到,后面更走不到了 + max = Math.max(nums[i] + i, max); + } + + return max >= nums.length - 1 +}; + +``` diff --git a/todo/10.regular-expression-matching.js b/todo/10.regular-expression-matching.js new file mode 100644 index 000000000..44bfc2a95 --- /dev/null +++ b/todo/10.regular-expression-matching.js @@ -0,0 +1,92 @@ +/* + * @lc app=leetcode id=10 lang=javascript + * + * [10] Regular Expression Matching + * + * https://leetcode.com/problems/regular-expression-matching/description/ + * + * algorithms + * Hard (25.00%) + * Total Accepted: 293.3K + * Total Submissions: 1.2M + * Testcase Example: '"aa"\n"a"' + * + * Given an input string (s) and a pattern (p), implement regular expression + * matching with support for '.' and '*'. + * + * + * '.' Matches any single character. + * '*' Matches zero or more of the preceding element. + * + * + * The matching should cover the entire input string (not partial). + * + * Note: + * + * + * s could be empty and contains only lowercase letters a-z. + * p could be empty and contains only lowercase letters a-z, and characters + * like . or *. + * + * + * Example 1: + * + * + * Input: + * s = "aa" + * p = "a" + * Output: false + * Explanation: "a" does not match the entire string "aa". + * + * + * Example 2: + * + * + * Input: + * s = "aa" + * p = "a*" + * Output: true + * Explanation: '*' means zero or more of the precedeng element, 'a'. + * Therefore, by repeating 'a' once, it becomes "aa". + * + * + * Example 3: + * + * + * Input: + * s = "ab" + * p = ".*" + * Output: true + * Explanation: ".*" means "zero or more (*) of any character (.)". + * + * + * Example 4: + * + * + * Input: + * s = "aab" + * p = "c*a*b" + * Output: true + * Explanation: c can be repeated 0 times, a can be repeated 1 time. Therefore + * it matches "aab". + * + * + * Example 5: + * + * + * Input: + * s = "mississippi" + * p = "mis*is*p*." + * Output: false + * + * + */ +/** + * @param {string} s + * @param {string} p + * @return {boolean} + */ +var isMatch = function(s, p) { + +}; + diff --git a/todo/365.water-and-jug-problem.js b/todo/365.water-and-jug-problem.js new file mode 100644 index 000000000..990612ab3 --- /dev/null +++ b/todo/365.water-and-jug-problem.js @@ -0,0 +1,53 @@ +/* + * @lc app=leetcode id=365 lang=javascript + * + * [365] Water and Jug Problem + * + * https://leetcode.com/problems/water-and-jug-problem/description/ + * + * algorithms + * Medium (28.76%) + * Total Accepted: 27K + * Total Submissions: 93.7K + * Testcase Example: '3\n5\n4' + * + * You are given two jugs with capacities x and y litres. There is an infinite + * amount of water supply available. You need to determine whether it is + * possible to measure exactly z litres using these two jugs. + * + * If z liters of water is measurable, you must have z liters of water + * contained within one or both buckets by the end. + * + * Operations allowed: + * + * + * Fill any of the jugs completely with water. + * Empty any of the jugs. + * Pour water from one jug into another till the other jug is completely full + * or the first jug itself is empty. + * + * + * Example 1: (From the famous "Die Hard" example) + * + * + * Input: x = 3, y = 5, z = 4 + * Output: True + * + * + * Example 2: + * + * + * Input: x = 2, y = 6, z = 5 + * Output: False + * + */ +/** + * @param {number} x + * @param {number} y + * @param {number} z + * @return {boolean} + */ +var canMeasureWater = function(x, y, z) { + const visited = {}; +}; +