diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..931e226
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,22 @@
+.DS_Store
+._*
+.cache
+.project
+.settings
+.tmproj
+*.esproj
+*.sublime-project
+*.sublime-workspace
+nbproject
+thumbs.db
+*.iml
+
+# Folders to ignore
+.hg
+.svn
+.CVS
+.idea
+node_modules/
+jscoverage_lib/
+bower_components/
+dist/
\ No newline at end of file
diff --git a/.prettierrc b/.prettierrc
new file mode 100644
index 0000000..6d334cc
--- /dev/null
+++ b/.prettierrc
@@ -0,0 +1,5 @@
+{
+ "printWidth": 80,
+ "tabWidth": 2,
+ "semi": false
+}
\ No newline at end of file
diff --git "a/BFS\351\227\256\351\242\230/\345\234\250\346\257\217\344\270\252\346\240\221\350\241\214\344\270\255\346\211\276\346\234\200\345\244\247\345\200\274-515.js" "b/BFS\351\227\256\351\242\230/\345\234\250\346\257\217\344\270\252\346\240\221\350\241\214\344\270\255\346\211\276\346\234\200\345\244\247\345\200\274-515.js"
new file mode 100644
index 0000000..59e7d54
--- /dev/null
+++ "b/BFS\351\227\256\351\242\230/\345\234\250\346\257\217\344\270\252\346\240\221\350\241\214\344\270\255\346\211\276\346\234\200\345\244\247\345\200\274-515.js"
@@ -0,0 +1,93 @@
+/**
+ * 您需要在二叉树的每一行中找到最大的值。
+
+ 示例:
+
+ 输入:
+
+ 5
+ / \
+ 14 2
+ / \ \
+ 1 3 9
+
+ 输出: [1, 3, 9]
+
+ 来源:力扣(LeetCode)
+ 链接:https://leetcode-cn.com/problems/find-largest-value-in-each-tree-row
+ 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
+ */
+
+/**
+ * Definition for a binary tree node.
+ * function TreeNode(val) {
+ * this.val = val;
+ * this.left = this.right = null;
+ * }
+ */
+/**
+ * @param {TreeNode} root
+ * @return {number[]}
+ */
+let largestValues = function (root) {
+ if (!root) return [];
+ let queue = [root];
+ let maximums = [];
+
+ while (queue.length) {
+ let max = Number.MIN_SAFE_INTEGER;
+ // 这里需要先缓存length 这个length代表当前层级的所有节点
+ // 在循环开始后 会push新的节点 length就不稳定了
+ let len = queue.length;
+ for (let i = 0; i < len; i++) {
+ let node = queue[i];
+ max = Math.max(node.val, max);
+
+ if (node.left) {
+ queue.push(node.left);
+ }
+ if (node.right) {
+ queue.push(node.right);
+ }
+ }
+
+ // 本「层级」处理完毕,截取掉。
+ queue.splice(0, len);
+
+ // 这个for循环结束后 代表当前层级的节点全部处理完毕
+ // 直接把计算出来的最大值push到数组里即可。
+ maximums.push(max);
+ }
+
+ return maximums;
+};
+
+/** test case **/
+function TreeNode(val) {
+ this.val = val;
+ this.left = this.right = null;
+}
+
+/** 预期:[1, 3, 9] */
+let root = new TreeNode(1);
+root.left = new TreeNode(3);
+root.right = new TreeNode(2);
+root.left.left = new TreeNode(5);
+root.left.right = new TreeNode(3);
+root.right.right = new TreeNode(9);
+
+/**
+ 5
+ /
+ 14
+ /
+ 1
+
+ */
+/** 预期:[5, 14, 1] */
+let root2 = new TreeNode(5);
+root2.left = new TreeNode(14);
+root2.left.left = new TreeNode(1);
+
+console.log(largestValues(root));
+console.log(largestValues(root2));
diff --git "a/BFS\351\227\256\351\242\230/\350\267\263\350\267\203\346\270\270\346\210\217 III-1306.js" "b/BFS\351\227\256\351\242\230/\350\267\263\350\267\203\346\270\270\346\210\217 III-1306.js"
new file mode 100644
index 0000000..73d910e
--- /dev/null
+++ "b/BFS\351\227\256\351\242\230/\350\267\263\350\267\203\346\270\270\346\210\217 III-1306.js"
@@ -0,0 +1,27 @@
+/**
+ * @param {number[]} arr
+ * @param {number} start
+ * @return {boolean}
+ */
+let canReach = function (arr, start) {
+ let n = arr.length
+ let visited = []
+ let queue = [start]
+ while (queue.length) {
+ let index = queue.pop()
+ let val = arr[index]
+ if (val === 0) {
+ return true
+ }
+ let left = index - val
+ let right = index + val
+ if (left >= 0 && !visited[left]) {
+ queue.push(left)
+ }
+ if (right < n && !visited[right]) {
+ queue.push(right)
+ }
+ visited[index] = true
+ }
+ return false
+};
\ No newline at end of file
diff --git "a/BFS\351\227\256\351\242\230/\350\267\263\350\267\203\346\270\270\346\210\217 IV-1345.js" "b/BFS\351\227\256\351\242\230/\350\267\263\350\267\203\346\270\270\346\210\217 IV-1345.js"
new file mode 100644
index 0000000..be115b2
--- /dev/null
+++ "b/BFS\351\227\256\351\242\230/\350\267\263\350\267\203\346\270\270\346\210\217 IV-1345.js"
@@ -0,0 +1,72 @@
+/**
+ * @param {number[]} arr
+ * @return {number}
+ */
+let minJumps = function (arr) {
+ let n = arr.length
+ if (n === 1) {
+ return 0
+ }
+
+ // 连续出现超过两次的数字就抛弃掉
+ let newArr = []
+ let sameCount = 0
+ for (let i = 0; i < arr.length; i++) {
+ if (arr[i] === arr[i - 1]) {
+ sameCount += 1
+ if (sameCount >= 2) {
+ continue
+ } else {
+ newArr.push(arr[i])
+ }
+ } else {
+ newArr.push(arr[i])
+ sameCount = 0
+ }
+ }
+ arr = newArr
+ n = arr.length
+ // 遍历一遍 记录每个数字出现的下标位置
+ let indexesMap = new Map()
+ for (let i = 0; i < n; i++) {
+ let val = arr[i]
+ let indexes = indexesMap.get(val)
+ if (!indexes) {
+ indexesMap.set(val, [i])
+ } else {
+ indexes.push(i)
+ }
+ }
+
+ let visited = []
+ let count = 0
+ let queue = [0]
+ while (queue.length) {
+ count++
+ let len = queue.length
+ for (let i = 0; i < len; i++) {
+ let index = queue.shift()
+ // 找到了 由于bfs的特性 此时用的跳跃次数一定是最少的
+ if (index === n - 1) {
+ return count - 1
+ }
+
+ // 没找到 继续把可以跳的几个位置都放入队列中
+ let val = arr[index]
+ let left = index - 1
+ let right = index + 1
+ let sameIndexes = indexesMap.get(val)
+
+ if (left >= 0 && !visited[left]) queue.push(left)
+ if (right < n && !visited[right]) queue.push(right)
+ for (let sameIndex of sameIndexes) {
+ if (sameIndex !== index && !visited[sameIndex]) {
+ queue.push(sameIndex)
+ }
+ }
+
+ visited[index] = true
+ }
+ }
+ return n
+}
diff --git "a/DFS\351\227\256\351\242\230/index.md" "b/DFS\351\227\256\351\242\230/index.md"
new file mode 100644
index 0000000..55b6081
--- /dev/null
+++ "b/DFS\351\227\256\351\242\230/index.md"
@@ -0,0 +1,47 @@
+# 社区看到的优解
+
+其实这题本身是我想复杂了,我是一个个格子去遍历,然后再上下左右去扩展延伸。
+
+但是其实只需要遍历四个边界上的节点,遇到 O 的边界点才开始蔓延遍历,并且把遍历到的节点都标记为 M(防止重复遍历)
+
+最后再一次性遍历整个二维数组,遇到 M 的标记都转为 O(因为是从边界蔓延的,一定是不符合 X 的条件的)。
+
+这样遍历所走的路就会少很多。
+
+```js
+let solve = function (board) {
+ if (board.length == 0) return null;
+
+ for (let y = 0; y < board.length; y++) {
+ for (let x = 0; x < board[0].length; x++) {
+ if (board[y][x] == "O" && (y == 0 || y == board.length - 1 || x == 0 || x == board[0].length - 1)) {
+ dfs(board, y, x);
+ }
+ }
+ }
+
+ for (let y = 0; y < board.length; y++) {
+ for (let x = 0; x < board[0].length; x++) {
+ if (board[y][x] == "W") {
+ board[y][x] = "O";
+ } else {
+ board[y][x] = "X";
+ }
+ }
+ }
+
+ return board;
+};
+
+function dfs(board, y, x) {
+ if (y < 0 || x < 0 || y >= board.length || x >= board[0].length || board[y][x] == "X" || board[y][x] == "W") {
+ return;
+ }
+ board[y][x] = "W";
+ dfs(board, y + 1, x);
+ dfs(board, y - 1, x);
+ dfs(board, y, x + 1);
+ dfs(board, y, x - 1);
+ return;
+}
+```
diff --git "a/DFS\351\227\256\351\242\230/\345\233\276\345\203\217\346\270\262\346\237\223-733.js" "b/DFS\351\227\256\351\242\230/\345\233\276\345\203\217\346\270\262\346\237\223-733.js"
new file mode 100644
index 0000000..2f554ad
--- /dev/null
+++ "b/DFS\351\227\256\351\242\230/\345\233\276\345\203\217\346\270\262\346\237\223-733.js"
@@ -0,0 +1,38 @@
+/**
+ * @param {number[][]} image
+ * @param {number} sr
+ * @param {number} sc
+ * @param {number} newColor
+ * @return {number[][]}
+ */
+let floodFill = function (image, sr, sc, newColor) {
+ let current = image[sr][sc];
+ dfs(image, sr, sc, current, newColor);
+ return image;
+};
+
+function dfs(image, sr, sc, current, newColor) {
+ let row = image[sr];
+ if (row === undefined) return;
+
+ let cell = row[sc];
+ if (cell === undefined || cell !== current || cell === newColor) return;
+
+ row[sc] = newColor;
+ dfs(image, sr + 1, sc, current, newColor);
+ dfs(image, sr - 1, sc, current, newColor);
+ dfs(image, sr, sc + 1, current, newColor);
+ dfs(image, sr, sc - 1, current, newColor);
+}
+
+console.log(
+ floodFill(
+ [
+ [0, 0, 0],
+ [0, 0, 0],
+ ],
+ 0,
+ 0,
+ 2
+ )
+);
diff --git "a/DFS\351\227\256\351\242\230/\345\262\233\345\261\277\346\225\260\351\207\217.js" "b/DFS\351\227\256\351\242\230/\345\262\233\345\261\277\346\225\260\351\207\217.js"
new file mode 100644
index 0000000..0d22d39
--- /dev/null
+++ "b/DFS\351\227\256\351\242\230/\345\262\233\345\261\277\346\225\260\351\207\217.js"
@@ -0,0 +1,62 @@
+/**
+ * 岛屿问题
+
+ 给定一个由 '1'(陆地)和 '0'(水)组成的的二维网格,计算岛屿的数量。一个岛被水包围,并且它是通过水平方向或垂直方向上相邻的陆地连接而成的。你可以假设网格的四个边均被水包围。
+
+ 示例 1:
+
+ 输入:
+ 11110
+ 11010
+ 11000
+ 00000
+
+ 输出: 1
+ 示例 2:
+
+ 输入:
+ 11000
+ 11000
+ 00100
+ 00011
+
+ 输出: 3
+
+ 来源:力扣(LeetCode)
+ 链接:https://leetcode-cn.com/problems/number-of-islands
+ 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
+ */
+let numIslands = function (grid) {
+ let count = 0
+ for (let i = 0; i < grid.length; i++) {
+ let row = grid[i]
+ for (let j = 0; j < row.length; j++) {
+ if (row[j] === '1') {
+ dfs(grid, i, j)
+ count++
+ }
+ }
+ }
+ return count
+};
+
+function dfs(grid, i, j) {
+ let point = grid[i] && grid[i][j]
+ if (point === '0' || point === undefined) {
+ return
+ }
+ grid[i][j] = '0'
+
+ dfs(grid, i - 1, j) // 上
+ dfs(grid, i + 1, j) // 下
+ dfs(grid, i, j - 1) // 左
+ dfs(grid, i, j + 1) // 右
+}
+
+/**
+ * 很经典的 dfs 问题,很棒很棒的思路,当找到一个点为1的时候,先记录数量加一。
+
+ 然后对于每个点递归的去遍历自己和上下左右的节点,如果值为1就置为0再继续遍历上下左右,这样直到遇到某一边本身就为0的时候停止。
+
+ 这样,一片 “值为1的岛屿” 就全部归零了。
+ */
\ No newline at end of file
diff --git "a/DFS\351\227\256\351\242\230/\345\262\233\345\261\277\347\232\204\345\221\250\351\225\277-463.js" "b/DFS\351\227\256\351\242\230/\345\262\233\345\261\277\347\232\204\345\221\250\351\225\277-463.js"
new file mode 100644
index 0000000..5586d3d
--- /dev/null
+++ "b/DFS\351\227\256\351\242\230/\345\262\233\345\261\277\347\232\204\345\221\250\351\225\277-463.js"
@@ -0,0 +1,68 @@
+// https://leetcode-cn.com/problems/island-perimeter
+/**
+ * @param {number[][]} grid
+ * @return {number}
+ */
+let islandPerimeter = function (grid) {
+ let yLen = grid.length;
+ if (!yLen) return 0;
+ let xLen = grid[0].length;
+
+ let perimeter = { value: 0 };
+
+ for (let y = 0; y < yLen; y++) {
+ for (let x = 0; x < xLen; x++) {
+ if (grid[y][x] === 1) {
+ dfs(grid, y, x, perimeter);
+ break;
+ }
+ }
+ }
+
+ return perimeter.value;
+};
+
+function dfs(grid, y, x, perimeter) {
+ let cell = grid[y][x];
+ if (cell === "COMPLETE") return;
+
+ grid[y][x] = "COMPLETE";
+
+ let below = grid[y - 1] && grid[y - 1][x];
+ let upper = grid[y + 1] && grid[y + 1][x];
+ let left = grid[y][x - 1];
+ let right = grid[y][x + 1];
+
+ if (below) {
+ dfs(grid, y - 1, x, perimeter);
+ } else {
+ perimeter.value++;
+ }
+
+ if (upper) {
+ dfs(grid, y + 1, x, perimeter);
+ } else {
+ perimeter.value++;
+ }
+
+ if (left) {
+ dfs(grid, y, x - 1, perimeter);
+ } else {
+ perimeter.value++;
+ }
+
+ if (right) {
+ dfs(grid, y, x + 1, perimeter);
+ } else {
+ perimeter.value++;
+ }
+}
+
+console.log(
+ islandPerimeter([
+ [0, 1, 0, 0],
+ [1, 1, 1, 0],
+ [0, 1, 0, 0],
+ [1, 1, 0, 0],
+ ])
+);
diff --git "a/DFS\351\227\256\351\242\230/\345\262\233\345\261\277\347\232\204\346\234\200\345\244\247\351\235\242\347\247\257-659.js" "b/DFS\351\227\256\351\242\230/\345\262\233\345\261\277\347\232\204\346\234\200\345\244\247\351\235\242\347\247\257-659.js"
new file mode 100644
index 0000000..2a46b59
--- /dev/null
+++ "b/DFS\351\227\256\351\242\230/\345\262\233\345\261\277\347\232\204\346\234\200\345\244\247\351\235\242\347\247\257-659.js"
@@ -0,0 +1,41 @@
+// https://github.com/sl1673495/daily-plan/issues/18
+
+/**
+ * @param {number[][]} grid
+ * @return {number}
+ */
+let maxAreaOfIsland = function (grid) {
+ let yLen = grid.length;
+ if (!yLen) return grid;
+ let xLen = grid[0].length;
+ let max = 0;
+
+ for (let y = 0; y < yLen; y++) {
+ for (let x = 0; x < xLen; x++) {
+ if (grid[y][x] === 1) {
+ let countRef = { current: 0 };
+ dfs(grid, y, x, countRef);
+ if (countRef.current > max) {
+ max = countRef.current;
+ }
+ }
+ }
+ }
+ return max;
+};
+
+function dfs(grid, y, x, countRef) {
+ if (!grid[y] || !grid[y][x] || grid[y][x] === 0 || grid[y][x] === "COMPLETE") {
+ return;
+ }
+
+ if (grid[y][x] === 1) {
+ grid[y][x] = "COMPLETE";
+ countRef.current++;
+ }
+
+ dfs(grid, y - 1, x, countRef);
+ dfs(grid, y + 1, x, countRef);
+ dfs(grid, y, x - 1, countRef);
+ dfs(grid, y, x + 1, countRef);
+}
\ No newline at end of file
diff --git "a/DFS\351\227\256\351\242\230/\350\242\253\345\233\264\347\273\225\347\232\204\345\214\272\345\237\237-\345\276\252\347\216\257\347\211\210.js" "b/DFS\351\227\256\351\242\230/\350\242\253\345\233\264\347\273\225\347\232\204\345\214\272\345\237\237-\345\276\252\347\216\257\347\211\210.js"
new file mode 100644
index 0000000..9665db3
--- /dev/null
+++ "b/DFS\351\227\256\351\242\230/\350\242\253\345\233\264\347\273\225\347\232\204\345\214\272\345\237\237-\345\276\252\347\216\257\347\211\210.js"
@@ -0,0 +1,142 @@
+/**
+给定一个二维的矩阵,包含 'X' 和 'O'(字母 O)。
+
+找到所有被 'X' 围绕的区域,并将这些区域里所有的 'O' 用 'X' 填充。
+
+示例:
+
+X X X X
+X O O X
+X X O X
+X O X X
+运行你的函数后,矩阵变为:
+
+X X X X
+X X X X
+X X X X
+X O X X
+解释:
+
+被围绕的区间不会存在于边界上,换句话说,任何边界上的 'O' 都不会被填充为 'X'。 任何不在边界上,或不与边界上的 'O' 相连的 'O' 最终都会被填充为 'X'。如果两个元素在水平或垂直方向相邻,则称它们是“相连”的。
+
+来源:力扣(LeetCode)
+链接:https://leetcode-cn.com/problems/surrounded-regions
+著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
+ */
+
+/**
+ * @param {character[][]} board
+ * @return {void} Do not return anything, modify board in-place instead.
+ */
+
+function genKey(i, j) {
+ return `${i}-${j}`;
+}
+
+let solve = function (board) {
+ const notXMap = {};
+ for (let i = 0; i < board.length; i++) {
+ let row = board[i];
+ for (let j = 0; j < row.length; j++) {
+ let cell = row[j];
+ if (cell === "O" && !notXMap[genKey(i, j)]) {
+ dfsIsValid(board, i, j, notXMap);
+ }
+ }
+ }
+ return board;
+};
+
+function getBoradValue(board, i, j) {
+ let row = board[i];
+ return row && row[j];
+}
+
+function dfsIsValid(board, currentI, currnetJ, notXMap) {
+ let queue = []; // 本次dfs走过的路径
+ let thisTimeFailed = { current: false };
+ let thisTimeHasHandledMap = {};
+ let checkQueue = [[currentI, currnetJ]];
+
+ while (checkQueue.length) {
+ const head = checkQueue.shift();
+ // 临时替换 标记为可替换节点
+ const [i, j] = head;
+ let row = board[i];
+ let cell = row && board[i][j];
+
+ // 已经在map中记录处理过的 整个链路都不可能为X
+ if (notXMap[genKey(i, j)]) {
+ continue;
+ }
+
+ // 本次路径失败
+ if (!cell) {
+ thisTimeFailed.current = true;
+ continue;
+ }
+
+ // 为X说明这一边符合条件
+ if (cell === "X") continue;
+
+ // 推到路径队列里,等到遍历完成决定该保留O还是换成X
+ queue.push([i, j]);
+
+ if (!thisTimeHasHandledMap[genKey(i - 1, j)] && !notXMap[genKey(i - 1, j)]) {
+ thisTimeHasHandledMap[genKey(i - 1, j)] = true;
+ checkQueue.push([i - 1, j])
+ };
+ if (!thisTimeHasHandledMap[genKey(i + 1, j)] && !notXMap[genKey(i + 1, j)]) {
+ thisTimeHasHandledMap[genKey(i + 1, j)] = true;
+ checkQueue.push([i + 1, j])
+ };
+ if (!thisTimeHasHandledMap[genKey(i, j - 1)] && !notXMap[genKey(i, j - 1)]) {
+ thisTimeHasHandledMap[genKey(i, j - 1)] = true;
+ checkQueue.push([i, j - 1])
+ };
+ if (!thisTimeHasHandledMap[genKey(i, j + 1)] && !notXMap[genKey(i, j + 1)]) {
+ thisTimeHasHandledMap[genKey(i, j + 1)] = true;
+ checkQueue.push([i, j + 1]);
+ }
+ }
+
+ // 循环结束后
+ // 如果本次循环遇到出界的情况 则全部记录在map中 后续遍历不再走这些格子
+ // 否则说明是被围绕的区域 赋值为X
+ if (queue.length) {
+ queue.forEach(([i, j]) => {
+ // 失败了 恢复O
+ if (thisTimeFailed.current) {
+ // 记录在map中 一定不会是X
+ notXMap[genKey(i, j)] = true;
+ } else {
+ board[i][j] = "X";
+ }
+ });
+ }
+}
+
+console.log(
+ solve([
+ ["X", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O"],
+ ["O", "X", "O", "O", "O", "O", "X", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "X", "X"],
+ ["O", "O", "O", "O", "O", "O", "O", "O", "X", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "X"],
+ ["O", "O", "X", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "X", "O"],
+ ["O", "O", "O", "O", "O", "X", "O", "O", "O", "O", "X", "O", "O", "O", "O", "O", "X", "O", "O", "X"],
+ ["X", "O", "O", "O", "X", "O", "O", "O", "O", "O", "X", "O", "X", "O", "X", "O", "X", "O", "X", "O"],
+ ["O", "O", "O", "O", "X", "O", "O", "X", "O", "O", "O", "O", "O", "X", "O", "O", "X", "O", "O", "O"],
+ ["X", "O", "O", "O", "X", "X", "X", "O", "X", "O", "O", "O", "O", "X", "X", "O", "X", "O", "O", "O"],
+ ["O", "O", "O", "O", "O", "X", "X", "X", "X", "O", "O", "O", "O", "X", "O", "O", "X", "O", "O", "O"],
+ ["X", "O", "O", "O", "O", "X", "O", "O", "O", "O", "O", "O", "X", "X", "O", "O", "X", "O", "O", "X"],
+ ["O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "X", "O", "O", "X", "O", "O", "O", "X", "O", "X"],
+ ["O", "O", "O", "O", "X", "O", "X", "O", "O", "X", "X", "O", "O", "O", "O", "O", "X", "O", "O", "O"],
+ ["X", "X", "O", "O", "O", "O", "O", "X", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O"],
+ ["O", "X", "O", "X", "O", "O", "O", "X", "O", "X", "O", "O", "O", "X", "O", "X", "O", "X", "O", "O"],
+ ["O", "O", "X", "O", "O", "O", "O", "O", "O", "O", "X", "O", "O", "O", "O", "O", "X", "O", "X", "O"],
+ ["X", "X", "O", "O", "O", "O", "O", "O", "O", "O", "X", "O", "X", "X", "O", "O", "O", "X", "O", "O"],
+ ["O", "O", "X", "O", "O", "O", "O", "O", "O", "O", "X", "O", "O", "X", "O", "X", "O", "X", "O", "O"],
+ ["O", "O", "O", "X", "O", "O", "O", "O", "O", "X", "X", "X", "O", "O", "X", "O", "O", "O", "X", "O"],
+ ["O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O"],
+ ["X", "O", "O", "O", "O", "X", "O", "O", "O", "X", "X", "O", "O", "X", "O", "X", "O", "X", "O", "O"],
+ ])
+);
diff --git "a/DFS\351\227\256\351\242\230/\350\242\253\345\233\264\347\273\225\347\232\204\345\214\272\345\237\237-\346\255\243\350\247\243\347\211\210.js" "b/DFS\351\227\256\351\242\230/\350\242\253\345\233\264\347\273\225\347\232\204\345\214\272\345\237\237-\346\255\243\350\247\243\347\211\210.js"
new file mode 100644
index 0000000..686b90a
--- /dev/null
+++ "b/DFS\351\227\256\351\242\230/\350\242\253\345\233\264\347\273\225\347\232\204\345\214\272\345\237\237-\346\255\243\350\247\243\347\211\210.js"
@@ -0,0 +1,46 @@
+// https://github.com/sl1673495/daily-plan/issues/16
+
+let solve = function (board) {
+ if (board.length == 0) return null;
+
+ for (let y = 0; y < board.length; y++) {
+ for (let x = 0; x < board[0].length; x++) {
+ if (board[y][x] == "O" && (y == 0 || y == board.length - 1 || x == 0 || x == board[0].length - 1)) {
+ dfs(board, y, x);
+ }
+ }
+ }
+
+ for (let y = 0; y < board.length; y++) {
+ for (let x = 0; x < board[0].length; x++) {
+ if (board[y][x] == "W") {
+ board[y][x] = "O";
+ } else {
+ board[y][x] = "X";
+ }
+ }
+ }
+
+ return board;
+};
+
+function dfs(board, y, x) {
+ if (y < 0 || x < 0 || y >= board.length || x >= board[0].length || board[y][x] == "X" || board[y][x] == "W") {
+ return;
+ }
+ board[y][x] = "W";
+ dfs(board, y + 1, x);
+ dfs(board, y - 1, x);
+ dfs(board, y, x + 1);
+ dfs(board, y, x - 1);
+ return;
+}
+
+console.log(
+ solve([
+ ["X", "X", "X", "X"],
+ ["X", "O", "O", "X"],
+ ["X", "X", "O", "X"],
+ ["X", "O", "X", "X"],
+ ])
+);
diff --git "a/DFS\351\227\256\351\242\230/\350\242\253\345\233\264\347\273\225\347\232\204\345\214\272\345\237\237.js" "b/DFS\351\227\256\351\242\230/\350\242\253\345\233\264\347\273\225\347\232\204\345\214\272\345\237\237.js"
new file mode 100644
index 0000000..716321b
--- /dev/null
+++ "b/DFS\351\227\256\351\242\230/\350\242\253\345\233\264\347\273\225\347\232\204\345\214\272\345\237\237.js"
@@ -0,0 +1,181 @@
+/**
+给定一个二维的矩阵,包含 'X' 和 'O'(字母 O)。
+
+找到所有被 'X' 围绕的区域,并将这些区域里所有的 'O' 用 'X' 填充。
+
+示例:
+
+X X X X
+X O O X
+X X O X
+X O X X
+运行你的函数后,矩阵变为:
+
+X X X X
+X X X X
+X X X X
+X O X X
+解释:
+
+被围绕的区间不会存在于边界上,换句话说,任何边界上的 'O' 都不会被填充为 'X'。 任何不在边界上,或不与边界上的 'O' 相连的 'O' 最终都会被填充为 'X'。如果两个元素在水平或垂直方向相邻,则称它们是“相连”的。
+
+来源:力扣(LeetCode)
+链接:https://leetcode-cn.com/problems/surrounded-regions
+著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
+ */
+
+/**
+ * @param {character[][]} board
+ * @return {void} Do not return anything, modify board in-place instead.
+ */
+
+function genKey(i, j) {
+ return `${i}-${j}`;
+}
+
+let solve = function (board) {
+ const notXMap = {};
+ for (let i = 0; i < board.length; i++) {
+ let row = board[i];
+ for (let j = 0; j < row.length; j++) {
+ let cell = row[j];
+ if (cell === "O") {
+ let queue = []; // 本次dfs走过的路径
+ let thisDfsFailed = { current: false };
+ dfsIsValid(board, i, j, notXMap, queue, thisDfsFailed);
+ }
+ }
+ }
+ for (let i = 0; i < board.length; i++) {
+ let row = board[i];
+ for (let j = 0; j < row.length; j++) {
+ let cell = row[j];
+ if (cell === "O" || cell === "SYMBOL") {
+ // 如果是X
+ if (!notXMap[genKey(i, j)]) {
+ board[i][j] = "X";
+ }
+ }
+ }
+ }
+ return board;
+};
+
+function dfsIsValid(board, i, j, notXMap, queue, thisDfsFailed) {
+ // 临时替换 标记为可替换节点
+ let row = board[i];
+ let cell = row && board[i][j];
+
+ // 已经在map中记录处理过的 整个链路都不可能为X
+ if (notXMap[genKey(i, j)]) {
+ return;
+ }
+
+ // 本次路径失败
+ if (!cell) {
+ thisDfsFailed.current = true;
+ return;
+ }
+
+ // 为X说明这一边符合条件
+ if (cell === "X") return;
+ // 为SYMBOL说明之前已经被临时标记过 继续检查别的边
+ if (cell === "SYMBOL") return;
+
+ board[i][j] = "SYMBOL";
+ // 这里才去记录路径,排除上面不需要处理的格子。
+ queue.push({ i, j });
+
+ // 为O的话,进一步DFS,直到遇到「边界(X、SYMBOL、undefined)」
+ dfsIsValid(board, i - 1, j, notXMap, queue, thisDfsFailed); // 上
+ dfsIsValid(board, i + 1, j, notXMap, queue, thisDfsFailed); // 下
+ dfsIsValid(board, i, j - 1, notXMap, queue, thisDfsFailed); // 左
+ dfsIsValid(board, i, j + 1, notXMap, queue, thisDfsFailed); // 右
+
+ // 如果DFS结束,queue的值没有被清空,说明这是符合条件的
+ if (queue.length) {
+ queue.forEach(({ i, j }) => {
+ // 失败了 恢复O
+ if (thisDfsFailed.current) {
+ board[i][j] = "O";
+ // 记录在map中 一定不会是X
+ notXMap[genKey(i, j)] = true;
+ }
+ });
+ }
+}
+
+console.log(
+ solve([
+ ["O", "X", "O", "O", "X", "X", "X", "O", "O", "O", "O", "O", "X", "O", "O", "O", "O", "X", "O", "X"],
+ ["X", "O", "X", "O", "O", "X", "X", "O", "O", "X", "O", "X", "O", "X", "O", "X", "X", "O", "O", "O"],
+ ["O", "X", "O", "O", "O", "X", "X", "X", "X", "O", "O", "O", "O", "O", "X", "X", "X", "X", "O", "X"],
+ ["X", "X", "O", "O", "O", "X", "X", "O", "O", "O", "X", "X", "X", "O", "O", "X", "O", "X", "X", "O"],
+ ["O", "X", "O", "X", "X", "O", "X", "O", "O", "O", "X", "O", "O", "X", "O", "O", "O", "O", "O", "X"],
+ ["X", "O", "O", "X", "O", "X", "O", "O", "O", "X", "X", "O", "X", "O", "O", "X", "O", "O", "O", "O"],
+ ["X", "O", "O", "O", "X", "X", "O", "O", "O", "O", "O", "X", "O", "O", "X", "O", "O", "O", "O", "X"],
+ ["X", "O", "O", "O", "X", "O", "X", "X", "X", "O", "X", "O", "X", "X", "X", "X", "O", "O", "O", "X"],
+ ["X", "O", "O", "X", "O", "O", "O", "X", "O", "O", "O", "O", "O", "O", "O", "O", "O", "X", "O", "X"],
+ ["O", "O", "O", "X", "O", "X", "X", "X", "X", "X", "X", "X", "X", "X", "O", "O", "O", "O", "X", "O"],
+ ["X", "O", "X", "O", "X", "O", "O", "X", "X", "X", "O", "X", "X", "O", "O", "X", "X", "O", "O", "O"],
+ ["O", "X", "O", "O", "X", "O", "O", "O", "O", "O", "O", "X", "X", "X", "X", "O", "O", "O", "X", "O"],
+ ["X", "O", "O", "O", "X", "X", "X", "O", "X", "O", "O", "O", "X", "O", "X", "O", "X", "O", "O", "X"],
+ ["O", "O", "O", "O", "X", "O", "X", "X", "O", "X", "O", "X", "O", "X", "X", "X", "X", "O", "O", "O"],
+ ["O", "X", "X", "O", "O", "O", "O", "X", "O", "O", "X", "X", "X", "O", "O", "X", "X", "O", "X", "O"],
+ ["X", "O", "X", "X", "X", "X", "X", "X", "O", "X", "X", "O", "X", "O", "O", "X", "O", "O", "O", "X"],
+ ["X", "O", "O", "O", "X", "O", "X", "O", "O", "X", "O", "X", "O", "O", "X", "O", "O", "X", "X", "X"],
+ ["O", "O", "X", "O", "O", "O", "O", "X", "O", "O", "X", "X", "O", "X", "X", "X", "O", "O", "O", "O"],
+ ["O", "O", "X", "O", "O", "O", "O", "O", "O", "X", "X", "O", "X", "O", "X", "O", "O", "O", "X", "X"],
+ ["X", "O", "O", "O", "X", "O", "X", "X", "X", "O", "O", "X", "O", "X", "O", "X", "X", "O", "O", "O"],
+ ])
+);
+
+//输入
+[
+ ["O", "X", "O", "O", "X", "X", "X", "O", "O", "O", "O", "O", "X", "O", "O", "O", "O", "X", "O", "X"],
+ ["X", "O", "X", "O", "O", "X", "X", "O", "O", "X", "O", "X", "O", "X", "O", "X", "X", "O", "O", "O"],
+ ["O", "X", "O", "O", "O", "X", "X", "X", "X", "O", "O", "O", "O", "O", "X", "X", "X", "X", "O", "X"],
+ ["X", "X", "O", "O", "O", "X", "X", "O", "O", "O", "X", "X", "X", "O", "O", "X", "O", "X", "X", "O"],
+ ["O", "X", "O", "X", "X", "O", "X", "O", "O", "O", "X", "O", "O", "X", "O", "O", "O", "O", "O", "X"],
+ ["X", "O", "O", "X", "O", "X", "O", "O", "O", "X", "X", "O", "X", "O", "O", "X", "O", "O", "O", "O"],
+ ["X", "O", "O", "O", "X", "X", "O", "O", "O", "O", "O", "X", "O", "O", "X", "O", "O", "O", "O", "X"],
+ ["X", "O", "O", "O", "X", "O", "X", "X", "X", "O", "X", "O", "X", "X", "X", "X", "O", "O", "O", "X"],
+ ["X", "O", "O", "X", "O", "O", "O", "X", "O", "O", "O", "O", "O", "O", "O", "O", "O", "X", "O", "X"],
+ ["O", "O", "O", "X", "O", "X", "X", "X", "X", "X", "X", "X", "X", "X", "O", "O", "O", "O", "X", "O"],
+ ["X", "O", "X", "O", "X", "O", "O", "X", "X", "X", "O", "X", "X", "O", "O", "X", "X", "O", "O", "O"],
+ ["O", "X", "O", "O", "X", "O", "O", "O", "O", "O", "O", "X", "X", "X", "X", "O", "O", "O", "X", "O"],
+ ["X", "O", "O", "O", "X", "X", "X", "O", "X", "O", "O", "O", "X", "O", "X", "O", "X", "O", "O", "X"],
+ ["O", "O", "O", "O", "X", "O", "X", "X", "O", "X", "O", "X", "O", "X", "X", "X", "X", "O", "O", "O"],
+ ["O", "X", "X", "O", "O", "O", "O", "X", "O", "O", "X", "X", "X", "O", "O", "X", "X", "O", "X", "O"],
+ ["X", "O", "X", "X", "X", "X", "X", "X", "O", "X", "X", "O", "X", "O", "O", "X", "O", "O", "O", "X"],
+ ["X", "O", "O", "O", "X", "O", "X", "O", "O", "X", "O", "X", "O", "O", "X", "O", "O", "X", "X", "X"],
+ ["O", "O", "X", "O", "O", "O", "O", "X", "O", "O", "X", "X", "O", "X", "X", "X", "O", "O", "O", "O"],
+ ["O", "O", "X", "O", "O", "O", "O", "O", "O", "X", "X", "O", "X", "O", "X", "O", "O", "O", "X", "X"],
+ ["X", "O", "O", "O", "X", "O", "X", "X", "X", "O", "O", "X", "O", "X", "O", "X", "X", "O", "O", "O"],
+];
+
+// 期望
+[
+ ["O", "X", "O", "O", "X", "X", "X", "O", "O", "O", "O", "O", "X", "O", "O", "O", "O", "X", "O", "X"],
+ ["X", "X", "X", "O", "O", "X", "X", "O", "O", "X", "O", "X", "O", "X", "O", "X", "X", "O", "O", "O"],
+ ["O", "X", "O", "O", "O", "X", "X", "X", "X", "O", "O", "O", "O", "O", "X", "X", "X", "X", "O", "X"],
+ ["X", "X", "O", "O", "O", "X", "X", "O", "O", "O", "X", "X", "X", "O", "O", "X", "O", "X", "X", "O"],
+ ["O", "X", "O", "X", "X", "X", "X", "O", "O", "O", "X", "X", "X", "X", "O", "O", "O", "O", "O", "X"],
+ ["X", "O", "O", "X", "X", "X", "O", "O", "O", "X", "X", "X", "X", "O", "O", "X", "O", "O", "O", "O"],
+ ["X", "O", "O", "O", "X", "X", "O", "O", "O", "O", "O", "X", "O", "O", "X", "O", "O", "O", "O", "X"],
+ ["X", "O", "O", "O", "X", "X", "X", "X", "X", "O", "X", "O", "X", "X", "X", "X", "O", "O", "O", "X"],
+ ["X", "O", "O", "X", "X", "X", "X", "X", "O", "O", "O", "O", "O", "O", "O", "O", "O", "X", "O", "X"],
+ ["O", "O", "O", "X", "X", "X", "X", "X", "X", "X", "X", "X", "X", "X", "O", "O", "O", "O", "X", "O"],
+ ["X", "O", "X", "O", "X", "X", "X", "X", "X", "X", "X", "X", "X", "O", "O", "X", "X", "O", "O", "O"],
+ ["O", "X", "O", "O", "X", "X", "X", "X", "X", "X", "X", "X", "X", "X", "X", "O", "O", "O", "X", "O"],
+ ["X", "O", "O", "O", "X", "X", "X", "X", "X", "X", "X", "X", "X", "X", "X", "O", "X", "O", "O", "X"],
+ ["O", "O", "O", "O", "X", "O", "X", "X", "O", "X", "X", "X", "X", "X", "X", "X", "X", "O", "O", "O"],
+ ["O", "X", "X", "O", "O", "O", "O", "X", "O", "O", "X", "X", "X", "X", "X", "X", "X", "O", "X", "O"],
+ ["X", "O", "X", "X", "X", "X", "X", "X", "O", "X", "X", "X", "X", "X", "X", "X", "O", "O", "O", "X"],
+ ["X", "O", "O", "O", "X", "O", "X", "O", "O", "X", "X", "X", "X", "X", "X", "O", "O", "X", "X", "X"],
+ ["O", "O", "X", "O", "O", "O", "O", "X", "O", "O", "X", "X", "X", "X", "X", "X", "O", "O", "O", "O"],
+ ["O", "O", "X", "O", "O", "O", "O", "O", "O", "X", "X", "X", "X", "X", "X", "O", "O", "O", "X", "X"],
+ ["X", "O", "O", "O", "X", "O", "X", "X", "X", "O", "O", "X", "O", "X", "O", "X", "X", "O", "O", "O"],
+];
+
+// 这个递归解法思路是对的,但是在最后一个测试用例爆栈了。
\ No newline at end of file
diff --git "a/JavaScript\351\232\217\347\254\224/async-to-generator.js" "b/JavaScript\351\232\217\347\254\224/async-to-generator.js"
deleted file mode 100644
index 4d3d2d4..0000000
--- "a/JavaScript\351\232\217\347\254\224/async-to-generator.js"
+++ /dev/null
@@ -1,65 +0,0 @@
-/**
- * async的执行原理
- * 其实就是自动执行generator函数
- * 暂时不考虑genertor的编译步骤(更复杂)
- */
-
-const getData = () =>
- new Promise(resolve => setTimeout(() => resolve("data"), 1000))
-
-// 这样的一个async函数 应该再1秒后打印data
-async function test() {
- const data = await getData()
- console.log('data: ', data);
- const data2 = await getData()
- console.log('data2: ', data2);
- return 'success'
-}
-
-// async函数会被编译成generator函数 (babel会编译成更本质的形态,这里我们直接用generator)
-function* testG() {
- // await被编译成了yield
- const data = yield getData()
- console.log('data: ', data);
- const data2 = yield getData()
- console.log('data2: ', data2);
- return 'success'
-}
-
-function asyncToGenerator(generatorFunc) {
- return function() {
- const gen = generatorFunc.apply(this, arguments)
-
- return new Promise((resolve, reject) => {
- function step(key, arg) {
- let generatorResult
- try {
- generatorResult = gen[key](arg)
- } catch (error) {
- return reject(error)
- }
-
- const { value, done } = generatorResult
-
- if (done) {
- return resolve(value)
- } else {
- return Promise.resolve(value).then(
- function onResolve(val) {
- step("next", val)
- },
- function onReject(err) {
- step("throw", err)
- },
- )
- }
- }
- step("next")
- })
- }
-}
-
-const testGAsync = asyncToGenerator(testG)
-testGAsync().then(result => {
- console.log(result)
-})
diff --git "a/JavaScript\351\232\217\347\254\224/combine-skus.js" "b/JavaScript\351\232\217\347\254\224/combine-skus.js"
deleted file mode 100644
index 8d2482f..0000000
--- "a/JavaScript\351\232\217\347\254\224/combine-skus.js"
+++ /dev/null
@@ -1,23 +0,0 @@
-var s1 = ['大陆', '港版', '日版']
-var s2 = ['64g', '32g']
-var s3 = ['金色', '黄色', '蓝色']
-var s4 = ['标准套餐1', '标准套餐2']
-
-var combind = (...arrs) => {
- var [head, ...rest] = arrs
- var backet = [...head]
- var _combine = (backet, ...rest) => {
- const results = []
- const [head, ...more] = rest
- if (!head) return backet
- head.forEach(item1 => {
- backet.forEach(item2 => {
- results.push(`${item2}-${item1}`)
- })
- })
- return _combine(results, ...more)
- }
- return _combine(backet, ...rest)
-}
-
-console.log(combind(s1, s2, s3, s4))
\ No newline at end of file
diff --git "a/JavaScript\351\232\217\347\254\224/promise-easy.js" "b/JavaScript\351\232\217\347\254\224/promise-easy.js"
deleted file mode 100644
index 75b20a2..0000000
--- "a/JavaScript\351\232\217\347\254\224/promise-easy.js"
+++ /dev/null
@@ -1,42 +0,0 @@
-/**
- * 仅实现异步链式调用的简化版
- */
-function Promise(excutor) {
- var self = this
- self.onResolvedCallback = [] // Promise resolve时的回调函数集,因为在Promise结束之前有可能有多个回调添加到它上面
- function resolve(value) {
- self.data = value
- self.onResolvedCallback.forEach(callback => callback(value))
- }
- excutor(resolve.bind(self))
-}
-Promise.prototype.then = function(onResolved) {
- var self = this
- return new Promise(resolve => {
- self.onResolvedCallback.push(function() {
- var result = onResolved(self.data)
- if (result instanceof Promise) {
- result.then(resolve)
- } else {
- resolve(result)
- }
- })
- })
-}
-
-new Promise(resolve => {
- setTimeout(() => {
- resolve(1)
- }, 500)
-})
- .then(res => {
- console.log(res)
- return new Promise(resolve => {
- setTimeout(() => {
- resolve(2)
- }, 500)
- })
- })
- .then(console.log)
-
-
\ No newline at end of file
diff --git "a/JavaScript\351\232\217\347\254\224/promise.js" "b/JavaScript\351\232\217\347\254\224/promise.js"
deleted file mode 100644
index 858ea57..0000000
--- "a/JavaScript\351\232\217\347\254\224/promise.js"
+++ /dev/null
@@ -1,202 +0,0 @@
-// https://github.com/xieranmaya/blog/issues/3
-
-function Promise(executor) {
- var self = this
- self.status = "pending" // Promise当前的状态
- self.data = undefined // Promise的值
- self.onResolvedCallback = [] // Promise resolve时的回调函数集,因为在Promise结束之前有可能有多个回调添加到它上面
- self.onRejectedCallback = [] // Promise reject时的回调函数集,因为在Promise结束之前有可能有多个回调添加到它上面
-
- function resolve(value) {
- if (self.status === "pending") {
- self.status = "resolved"
- self.data = value
- for (var i = 0; i < self.onResolvedCallback.length; i++) {
- self.onResolvedCallback[i](value)
- }
- }
- }
-
- function reject(reason) {
- if (self.status === "pending") {
- self.status = "rejected"
- self.data = reason
- for (var i = 0; i < self.onRejectedCallback.length; i++) {
- self.onRejectedCallback[i](reason)
- }
- }
- }
-
- try {
- // 考虑到执行executor的过程中有可能出错,所以我们用try/catch块给包起来,并且在出错后以catch到的值reject掉这个Promise
- executor(resolve, reject) // 执行executor
- } catch (e) {
- reject(e)
- }
-}
-Promise.prototype.then = function(onResolved, onRejected) {
- var self = this
- var promise2
-
- // 根据标准,如果then的参数不是function,则我们需要忽略它,此处以如下方式处理
- // 并且默认函数需要return值 以便于空值的穿透
- onResolved =
- typeof onResolved === "function"
- ? onResolved
- : function(value) {
- return value
- }
- onRejected =
- typeof onRejected === "function"
- ? onRejected
- : function(reason) {
- return reason
- }
-
- if (self.status === "resolved") {
- // 如果promise1(此处即为this/self)的状态已经确定并且是resolved,我们调用onResolved
- // 因为考虑到有可能throw,所以我们将其包在try/catch块里
- return (promise2 = new Promise(function(resolve, reject) {
- try {
- var x = onResolved(self.data)
- resolvePromise(promise2, x, resolve, reject)
- } catch (e) {
- reject(e) // 如果出错,以捕获到的错误做为promise2的结果
- }
- }))
- }
-
- // 此处与前一个if块的逻辑几乎相同,区别在于所调用的是onRejected函数,就不再做过多解释
- if (self.status === "rejected") {
- return (promise2 = new Promise(function(resolve, reject) {
- try {
- var x = onRejected(self.data)
- resolvePromise(promise2, x, resolve, reject)
- } catch (e) {
- reject(e)
- }
- }))
- }
-
- if (self.status === "pending") {
- // 如果当前的Promise还处于pending状态,我们并不能确定调用onResolved还是onRejected,
- // 只能等到Promise的状态确定后,才能确实如何处理。
- // 所以我们需要把我们的**两种情况**的处理逻辑做为callback放入promise1(此处即this/self)的回调数组里
- // 逻辑本身跟第一个if块内的几乎一致,此处不做过多解释
- return (promise2 = new Promise(function(resolve, reject) {
- self.onResolvedCallback.push(function(value) {
- try {
- var x = onResolved(self.data)
- resolvePromise(promise2, x, resolve, reject)
- } catch (e) {
- reject(e)
- }
- })
-
- self.onRejectedCallback.push(function(reason) {
- try {
- var x = onRejected(self.data)
- resolvePromise(promise2, x, resolve, reject)
- } catch (e) {
- reject(e)
- }
- })
- }))
- }
-}
-
-/*
-resolvePromise函数即为根据x的值来决定promise2的状态的函数
-也即标准中的[Promise Resolution Procedure](https://promisesaplus.com/#point-47)
-x为`promise2 = promise1.then(onResolved, onRejected)`里`onResolved/onRejected`的返回值
-`resolve`和`reject`实际上是`promise2`的`executor`的两个实参,因为很难挂在其它的地方,所以一并传进来。
-相信各位一定可以对照标准把标准转换成代码,这里就只标出代码在标准中对应的位置,只在必要的地方做一些解释
-*/
-function resolvePromise(promise2, x, resolve, reject) {
- var then
- var thenCalledOrThrow = false
-
- // 对应标准2.3.1节
- // If promise and x refer to the same object, reject promise with a TypeError as the reason.
- if (promise2 === x) {
- return reject(new TypeError("Chaining cycle detected for promise!"))
- }
-
- // 2.3.2
- /**
- * If x is a promise, adopt its state [3.4]:
- If x is pending, promise must remain pending until x is fulfilled or rejected.
- If/when x is fulfilled, fulfill promise with the same value.
- If/when x is rejected, reject promise with the same reason.
- */
-
- if (x instanceof Promise) {
- // 对应标准2.3.2节
- // 如果x的状态还没有确定,那么它是有可能被一个thenable决定最终状态和值的 有可能x是个promise但是它resolve的又是一个promise
- // 比如
- // 所以这里需要做一下处理,而不能一概的以为它会被一个“正常”的值resolve
- if (x.status === "pending") {
- x.then(function(value) {
- resolvePromise(promise2, value, resolve, reject)
- }, reject)
- } else {
- // 但如果这个Promise的状态已经确定了,那么它肯定有一个“正常”的值,而不是一个thenable,所以这里直接取它的状态
- x.then(resolve, reject)
- }
- return
- }
-
- if (x !== null && (typeof x === "object" || typeof x === "function")) {
- // 2.3.3
- try {
- // 2.3.3.1 因为x.then有可能是一个getter,这种情况下多次读取就有可能产生副作用
- // 即要判断它的类型,又要调用它,这就是两次读取
- then = x.then
-
- if (typeof then === "function") {
- // 2.3.3.3
- then.call(
- x,
- function rs(y) {
- // 2.3.3.3.1
- if (thenCalledOrThrow) return
- thenCalledOrThrow = true
- return resolvePromise(promise2, y, resolve, reject) // 2.3.3.3.1
- },
- function rj(r) {
- if (thenCalledOrThrow) return // 2.3.3.3.3 即这三处谁选执行就以谁的结果为准
- thenCalledOrThrow = true
- return reject(r)
- },
- )
- } else {
- resolve(x)
- }
- } catch (e) {
- if (thenCalledOrThrow) return // 2.3.3.3.3 即这三处谁选执行就以谁的结果为准
- thenCalledOrThrow = true
- return reject(e)
- }
- } else {
- resolve(x)
- }
-}
-
-var a = new Promise(resolve => {
- setTimeout(() => {
- resolve(1)
- }, 500)
-})
- .then(res => {
- console.log("res1", res)
- return new Promise(r => {
- r(
- new Promise(r1 => {
- r1(15)
- }),
- )
- })
- })
- .then(res => {
- console.log("res2", res)
- })
diff --git "a/JavaScript\351\232\217\347\254\224/scroll.js" "b/JavaScript\351\232\217\347\254\224/scroll.js"
deleted file mode 100644
index 7ae2acd..0000000
--- "a/JavaScript\351\232\217\347\254\224/scroll.js"
+++ /dev/null
@@ -1,48 +0,0 @@
-export const raf = (() => {
- return window.requestAnimationFrame ||
- window.webkitRequestAnimationFrame ||
- window.mozRequestAnimationFrame ||
- window.oRequestAnimationFrame ||
- window.msRequestAnimationFrame ||
- function (callback) {
- window.setTimeout(callback, 1000 / 60)
- }
-})()
-
-let isScrolling = false
-let stop = false
-
-export function scroll (el, type, targetPos, time, next) {
- if (isScrolling) {
- stop = true
- }
- isScrolling = true
- const start = Date.now()
- const currentPos = el[type]
-
- raf(step)
-
- function step () {
- const current = Date.now()
- const rate = Math.min(1, (current - start) / time)
- if (rate === 1) {
- el[type] = targetPos
- isScrolling = false
- next && next()
- } else {
- el[type] = currentPos + (targetPos - currentPos) * rate
- if (!stop) {
- raf(step)
- } else {
- stop = false
- }
- }
- }
-}
-
-document.addEventListener('visibilitychange', () => {
- if (!document.hidden) {
- isScrolling = false
- stop = false
- }
-})
\ No newline at end of file
diff --git "a/LRU\347\274\223\345\255\230.js" "b/LRU\347\274\223\345\255\230.js"
new file mode 100644
index 0000000..25d09e7
--- /dev/null
+++ "b/LRU\347\274\223\345\255\230.js"
@@ -0,0 +1,94 @@
+class DoubleNode {
+ constructor(key, val) {
+ this.key = key
+ this.val = val
+
+ this.prev = null
+ this.next = null
+ }
+}
+
+class LRUCache {
+ constructor(max) {
+ this.max = max
+ this.map = new Map()
+
+ this.head = null
+ this.tail = null
+ }
+
+ get(key) {
+ const node = this.map.get(key)
+ if (!node) {
+ return -1
+ } else {
+ const res = node.val
+ this.remove(node)
+ this.appendHead(node)
+ return res
+ }
+ }
+
+ put(key, value) {
+ let node = this.map.get(key)
+ // 有这个缓存
+ if (node) {
+ node.val = value
+ // 新加入的 放在最前面
+ this.remove(node)
+ this.appendHead(node)
+ } else {
+ // 没有这个缓存
+ node = new DoubleNode(key, value)
+ // 如果超出容量了 删除最后一个 再放到头部
+ if (this.map.size >= this.max) {
+ this.map.delete(this.tail.key)
+ this.remove(this.tail)
+ this.appendHead(node)
+ this.map.set(key, node)
+ } else {
+ // 未超出容量 就直接放到头部
+ this.appendHead(node)
+ this.map.set(key, node)
+ }
+ }
+ }
+
+ /**
+ * 把头部指针的改变成新的node
+ * @param {DoubleNode} node
+ */
+ appendHead(node) {
+ if (this.head === null) {
+ this.head = this.tail = node
+ } else {
+ node.next = this.head
+ this.head.prev = node
+ this.head = node
+ }
+ }
+
+ /**
+ * 删除某个节点
+ * @param {DoubleNode} node
+ */
+ remove(node) {
+ if (this.head === this.tail) {
+ this.head = this.tail = null
+ } else {
+ // 删除头部
+ if (this.head === node) {
+ this.head = this.head.next
+ node.next = null
+ } else if (this.tail === node) {
+ this.tail = this.tail.prev
+ this.tail.next = null
+ node.prev = null
+ } else {
+ node.prev.next = node.next
+ node.next.prev = node.prev
+ node.prev = node.next = null
+ }
+ }
+ }
+}
diff --git a/README.md b/README.md
index 7036898..11f4963 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,359 @@
-# frontend-code-fragment
-前端代码片段,想到什么写什么。
+
Welcome to leetcode-javascript 👋
+
+
+
+
+
+
+> 力扣的题解记录(JavaScript)
+
+## 关于我
+大家好,我是 ssh,现在在字节跳动的 Web Infra 担任前端工程师,微信:**[sshsunlight](https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/017d568dc1d14cd883cc3238350a39ec~tplv-k3u1fbpfcp-watermark.image)**,欢迎找我交个朋友。
+
+一些算法相关的资料,我放在「前端从进阶到入院」公众号里了,回复「资料」即可获取。
+
+
+
+## 调试
+
+提供了 .vscode 配置文件,在 vscode 中选择「小爬虫」图标,点击启动程序,即可启动断点调试。
+
+## 思路
+
+思路会记录在本仓库的 Issues 中,按照 label 进行分类。比如想查看 「DFS」 分类下的问题,那么选择标签进行筛选即可。
+
+## 目录
+
+
+### 例题详解
+
+[最接近的三数之和-16](https://github.com/sl1673495/leetcode-javascript/issues/115)
+
+[分发饼干-455](https://github.com/sl1673495/leetcode-javascript/issues/88)
+
+[N皇后-51](https://github.com/sl1673495/leetcode-javascript/issues/78)
+
+[单词搜索-79](https://github.com/sl1673495/leetcode-javascript/issues/77)
+
+[二进制手表-401](https://github.com/sl1673495/leetcode-javascript/issues/76)
+
+[电话号码的字母组合-17](https://github.com/sl1673495/leetcode-javascript/issues/65)
+
+[二叉树的所有路径-257](https://github.com/sl1673495/leetcode-javascript/issues/59)
+
+[路径总和-112](https://github.com/sl1673495/leetcode-javascript/issues/57)
+
+[两两交换链表中的节点-24](https://github.com/sl1673495/leetcode-javascript/issues/51)
+
+[有效的括号-20](https://github.com/sl1673495/leetcode-javascript/issues/48)
+
+[无重复字符的最长子串-3](https://github.com/sl1673495/leetcode-javascript/issues/42)
+
+[二分查找-704](https://github.com/sl1673495/leetcode-javascript/issues/23)
+
+### 递归与回溯
+
+[跳水板-面试题 16.11 ](https://github.com/sl1673495/leetcode-javascript/issues/118)
+
+[顺次数-1291](https://github.com/sl1673495/leetcode-javascript/issues/116)
+
+[螺旋矩阵 II-59](https://github.com/sl1673495/leetcode-javascript/issues/113)
+
+[螺旋矩阵-54](https://github.com/sl1673495/leetcode-javascript/issues/112)
+
+[矩阵置零-73](https://github.com/sl1673495/leetcode-javascript/issues/111)
+
+[不同路径 III-980](https://github.com/sl1673495/leetcode-javascript/issues/107)
+
+[字母大小写全排列-784](https://github.com/sl1673495/leetcode-javascript/issues/106)
+
+[黄金矿工-1219](https://github.com/sl1673495/leetcode-javascript/issues/105)
+
+[有重复字符串的排列组合-面试题 08.08](https://github.com/sl1673495/leetcode-javascript/issues/104)
+
+[单词搜索 II-212](https://github.com/sl1673495/leetcode-javascript/issues/92)
+
+[解数独-37](https://github.com/sl1673495/leetcode-javascript/issues/79)
+
+[N皇后-51](https://github.com/sl1673495/leetcode-javascript/issues/78)
+
+[单词搜索-79](https://github.com/sl1673495/leetcode-javascript/issues/77)
+
+[二进制手表-401](https://github.com/sl1673495/leetcode-javascript/issues/76)
+
+[子集 II-90](https://github.com/sl1673495/leetcode-javascript/issues/75)
+
+[ 组合总和 III-216](https://github.com/sl1673495/leetcode-javascript/issues/74)
+
+[组合总和 II-40](https://github.com/sl1673495/leetcode-javascript/issues/73)
+
+[组合总和-39](https://github.com/sl1673495/leetcode-javascript/issues/72)
+
+[子集-78](https://github.com/sl1673495/leetcode-javascript/issues/71)
+
+[组合-77](https://github.com/sl1673495/leetcode-javascript/issues/70)
+
+[全排列 II-47](https://github.com/sl1673495/leetcode-javascript/issues/69)
+
+[全排列-46](https://github.com/sl1673495/leetcode-javascript/issues/68)
+
+[分割回文串-131](https://github.com/sl1673495/leetcode-javascript/issues/67)
+
+[复原IP地址-93](https://github.com/sl1673495/leetcode-javascript/issues/66)
+
+[电话号码的字母组合-17](https://github.com/sl1673495/leetcode-javascript/issues/65)
+
+[括号生成-22](https://github.com/sl1673495/leetcode-javascript/issues/31)
+
+### 动态规划
+
+[最长的斐波那契子序列的长度-873](https://github.com/sl1673495/leetcode-javascript/issues/117)
+
+[最长重复子数组-718](https://github.com/sl1673495/leetcode-javascript/issues/114)
+
+[下降路径最小和-931](https://github.com/sl1673495/leetcode-javascript/issues/108)
+
+[最大正方形-221](https://github.com/sl1673495/leetcode-javascript/issues/101)
+
+[恢复空格-面试题 17.13](https://github.com/sl1673495/leetcode-javascript/issues/100)
+
+[最长单词-面试题 17.15](https://github.com/sl1673495/leetcode-javascript/issues/99)
+
+[单词拆分 II-140](https://github.com/sl1673495/leetcode-javascript/issues/95)
+
+[单词拆分-139](https://github.com/sl1673495/leetcode-javascript/issues/93)
+
+[最长回文子串-5](https://github.com/sl1673495/leetcode-javascript/issues/91)
+
+[无重叠区间-435](https://github.com/sl1673495/leetcode-javascript/issues/90)
+
+[目标和-494](https://github.com/sl1673495/leetcode-javascript/issues/87)
+
+[一和零-474](https://github.com/sl1673495/leetcode-javascript/issues/86)
+
+[最长公共子序列-1143](https://github.com/sl1673495/leetcode-javascript/issues/85)
+
+[摆动序列-376](https://github.com/sl1673495/leetcode-javascript/issues/84)
+
+[最长上升子序列-300](https://github.com/sl1673495/leetcode-javascript/issues/83)
+
+[最长等差数列-1027](https://github.com/sl1673495/leetcode-javascript/issues/82)
+
+[解码方法-91](https://github.com/sl1673495/leetcode-javascript/issues/81)
+
+[三角形最小路径和-120](https://github.com/sl1673495/leetcode-javascript/issues/80)
+
+[最小路径和-64](https://github.com/sl1673495/leetcode-javascript/issues/34)
+
+[括号生成-22](https://github.com/sl1673495/leetcode-javascript/issues/31)
+
+[爬楼梯-70](https://github.com/sl1673495/leetcode-javascript/issues/22)
+
+[买卖股票的最佳时机-121](https://github.com/sl1673495/leetcode-javascript/issues/19)
+
+### 双指针
+
+[最接近的三数之和-16](https://github.com/sl1673495/leetcode-javascript/issues/115)
+
+[通过删除字母匹配到字典里最长单词-524](https://github.com/sl1673495/leetcode-javascript/issues/98)
+
+[搜索二维矩阵 II-240](https://github.com/sl1673495/leetcode-javascript/issues/96)
+
+[判断子序列-392](https://github.com/sl1673495/leetcode-javascript/issues/89)
+
+[分发饼干-455](https://github.com/sl1673495/leetcode-javascript/issues/88)
+
+[验证回文串-125](https://github.com/sl1673495/leetcode-javascript/issues/33)
+
+[两数之和 II - 输入有序数组-167](https://github.com/sl1673495/leetcode-javascript/issues/32)
+
+[合并两个有序数组-88](https://github.com/sl1673495/leetcode-javascript/issues/29)
+
+[移动零-283](https://github.com/sl1673495/leetcode-javascript/issues/26)
+
+### 前缀和
+
+[和为K的子数组-560](https://github.com/sl1673495/leetcode-javascript/issues/110)
+
+### 位运算
+
+[找不同-389](https://github.com/sl1673495/leetcode-javascript/issues/109)
+
+### 查找表
+
+[找不同-389](https://github.com/sl1673495/leetcode-javascript/issues/109)
+
+[两个数组的交集 II-350](https://github.com/sl1673495/leetcode-javascript/issues/37)
+
+### BFS
+
+[跳跃游戏 IV-1345](https://github.com/sl1673495/leetcode-javascript/issues/103)
+
+[跳跃游戏 III-1306](https://github.com/sl1673495/leetcode-javascript/issues/102)
+
+[二叉树的最小深度-111](https://github.com/sl1673495/leetcode-javascript/issues/54)
+
+[二叉树的最大深度-104](https://github.com/sl1673495/leetcode-javascript/issues/53)
+
+[二叉树的右视图-199](https://github.com/sl1673495/leetcode-javascript/issues/52)
+
+[二叉树的层序遍历-102](https://github.com/sl1673495/leetcode-javascript/issues/30)
+
+[相同的树-100](https://github.com/sl1673495/leetcode-javascript/issues/21)
+
+### 排序
+
+[最长单词-面试题 17.15](https://github.com/sl1673495/leetcode-javascript/issues/99)
+
+[通过删除字母匹配到字典里最长单词-524](https://github.com/sl1673495/leetcode-javascript/issues/98)
+
+[快速排序](https://github.com/sl1673495/leetcode-javascript/issues/41)
+
+[颜色分类-75](https://github.com/sl1673495/leetcode-javascript/issues/28)
+
+### 链表
+
+[移除链表元素-203](https://github.com/sl1673495/leetcode-javascript/issues/97)
+
+[两数相加-3](https://github.com/sl1673495/leetcode-javascript/issues/94)
+
+[两两交换链表中的节点-24](https://github.com/sl1673495/leetcode-javascript/issues/51)
+
+[删除链表的倒数第N个节点-19](https://github.com/sl1673495/leetcode-javascript/issues/46)
+
+[删除链表的节点-面试题18](https://github.com/sl1673495/leetcode-javascript/issues/40)
+
+[反转链表II-92](https://github.com/sl1673495/leetcode-javascript/issues/39)
+
+[反转链表 206](https://github.com/sl1673495/leetcode-javascript/issues/38)
+
+### 贪心算法
+
+[判断子序列-392](https://github.com/sl1673495/leetcode-javascript/issues/89)
+
+[分发饼干-455](https://github.com/sl1673495/leetcode-javascript/issues/88)
+
+[买卖股票的最佳时机 II-122](https://github.com/sl1673495/leetcode-javascript/issues/20)
+
+### DFS
+
+[二叉树的最近公共祖先-236](https://github.com/sl1673495/leetcode-javascript/issues/64)
+
+[将有序数组转换为二叉搜索树](https://github.com/sl1673495/leetcode-javascript/issues/63)
+
+[删除二叉搜索树中的节点-450](https://github.com/sl1673495/leetcode-javascript/issues/62)
+
+[路径总和 III-437](https://github.com/sl1673495/leetcode-javascript/issues/61)
+
+[求根到叶子节点数字之和-129](https://github.com/sl1673495/leetcode-javascript/issues/60)
+
+[二叉树的所有路径-257](https://github.com/sl1673495/leetcode-javascript/issues/59)
+
+[左叶子之和-404](https://github.com/sl1673495/leetcode-javascript/issues/58)
+
+[路径总和-112](https://github.com/sl1673495/leetcode-javascript/issues/57)
+
+[平衡二叉树-110](https://github.com/sl1673495/leetcode-javascript/issues/56)
+
+[对称二叉树-101](https://github.com/sl1673495/leetcode-javascript/issues/55)
+
+[二叉树的最小深度-111](https://github.com/sl1673495/leetcode-javascript/issues/54)
+
+[二叉树的最大深度-104](https://github.com/sl1673495/leetcode-javascript/issues/53)
+
+[二叉树的层序遍历-102](https://github.com/sl1673495/leetcode-javascript/issues/30)
+
+[路径总和 II-113](https://github.com/sl1673495/leetcode-javascript/issues/27)
+
+[相同的树-100](https://github.com/sl1673495/leetcode-javascript/issues/21)
+
+### 二叉树
+
+[二叉树的最近公共祖先-236](https://github.com/sl1673495/leetcode-javascript/issues/64)
+
+[将有序数组转换为二叉搜索树](https://github.com/sl1673495/leetcode-javascript/issues/63)
+
+[删除二叉搜索树中的节点-450](https://github.com/sl1673495/leetcode-javascript/issues/62)
+
+[路径总和 III-437](https://github.com/sl1673495/leetcode-javascript/issues/61)
+
+[求根到叶子节点数字之和-129](https://github.com/sl1673495/leetcode-javascript/issues/60)
+
+[二叉树的所有路径-257](https://github.com/sl1673495/leetcode-javascript/issues/59)
+
+[左叶子之和-404](https://github.com/sl1673495/leetcode-javascript/issues/58)
+
+[路径总和-112](https://github.com/sl1673495/leetcode-javascript/issues/57)
+
+[平衡二叉树-110](https://github.com/sl1673495/leetcode-javascript/issues/56)
+
+[对称二叉树-101](https://github.com/sl1673495/leetcode-javascript/issues/55)
+
+[二叉树的最小深度-111](https://github.com/sl1673495/leetcode-javascript/issues/54)
+
+[二叉树的最大深度-104](https://github.com/sl1673495/leetcode-javascript/issues/53)
+
+[二叉树的右视图-199](https://github.com/sl1673495/leetcode-javascript/issues/52)
+
+[二叉树的前序遍历-144](https://github.com/sl1673495/leetcode-javascript/issues/50)
+
+[二叉树的层序遍历-102](https://github.com/sl1673495/leetcode-javascript/issues/30)
+
+[路径总和 II-113](https://github.com/sl1673495/leetcode-javascript/issues/27)
+
+[相同的树-100](https://github.com/sl1673495/leetcode-javascript/issues/21)
+
+### 栈和队列
+
+[二叉树的右视图-199](https://github.com/sl1673495/leetcode-javascript/issues/52)
+
+[二叉树的前序遍历-144](https://github.com/sl1673495/leetcode-javascript/issues/50)
+
+[简化路径-71](https://github.com/sl1673495/leetcode-javascript/issues/49)
+
+[有效的括号-20](https://github.com/sl1673495/leetcode-javascript/issues/48)
+
+[逆波兰表达式求值-150](https://github.com/sl1673495/leetcode-javascript/issues/47)
+
+### 滑动窗口
+
+[滑动窗口的最大值-239](https://github.com/sl1673495/leetcode-javascript/issues/45)
+
+[找到字符串中所有字母异位词-438](https://github.com/sl1673495/leetcode-javascript/issues/44)
+
+[最小覆盖子串-76](https://github.com/sl1673495/leetcode-javascript/issues/43)
+
+[无重复字符的最长子串-3](https://github.com/sl1673495/leetcode-javascript/issues/42)
+
+[长度最小的子数组-209](https://github.com/sl1673495/leetcode-javascript/issues/36)
+
+### 数据结构
+
+[LRU 缓存机制-146](https://github.com/sl1673495/leetcode-javascript/issues/35)
+
+### 二分查找
+
+[Pow(x, n)-50](https://github.com/sl1673495/leetcode-javascript/issues/25)
+
+[x 的平方根-69](https://github.com/sl1673495/leetcode-javascript/issues/24)
+
+[二分查找-704](https://github.com/sl1673495/leetcode-javascript/issues/23)
+
+## Author
+
+👤 **ssh**
+
+- Website: https://ssh-blog.now.sh
+- Github: [@sl1673495](https://github.com/sl1673495)
+
+## 🤝 Contributing
+
+Contributions, issues and feature requests are welcome!
Feel free to check [issues page](https://github.com/sl1673495/leetcode-javascript/issues).
+
+## Show your support
+
+Give a ⭐️ if this project helped you!
+
+---
+
+_This README was generated with ❤️ by [readme-md-generator](https://github.com/kefranabg/readme-md-generator)_
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..3c48796
--- /dev/null
+++ b/package.json
@@ -0,0 +1,5 @@
+{
+ "devDependencies": {
+ "glob": "^7.1.6"
+ }
+}
diff --git "a/\347\256\227\346\263\225/\344\270\211\346\225\260\344\271\213\345\222\214.js" "b/\344\270\211\346\225\260\344\271\213\345\222\214.js"
similarity index 81%
rename from "\347\256\227\346\263\225/\344\270\211\346\225\260\344\271\213\345\222\214.js"
rename to "\344\270\211\346\225\260\344\271\213\345\222\214.js"
index d2514d9..f44621b 100644
--- "a/\347\256\227\346\263\225/\344\270\211\346\225\260\344\271\213\345\222\214.js"
+++ "b/\344\270\211\346\225\260\344\271\213\345\222\214.js"
@@ -2,9 +2,9 @@
* @param {number[]} nums
* @return {number[][]}
*/
-var twoSum = function(nums, target) {
+let twoSum = function(nums, target) {
let map = new Map()
- var results = []
+ let results = []
for (let i = 0; i < nums.length; i++) {
let num = nums[i]
let result = map.get(target - num)
@@ -16,11 +16,11 @@ var twoSum = function(nums, target) {
return results
}
-var threeSum = function(nums) {
+let threeSum = function(nums) {
nums.sort((a, b) => a - b)
- var set = new Set()
- var results = []
- for (var i = 0; i < nums.length - 2; i++) {
+ let set = new Set()
+ let results = []
+ for (let i = 0; i < nums.length - 2; i++) {
let find = twoSum(nums.slice(i + 1), -nums[i])
if (find) {
find.forEach((arr) => {
diff --git "a/\344\270\244\344\270\252\346\225\260\347\273\204\347\232\204\344\272\244\351\233\206II-350.js" "b/\344\270\244\344\270\252\346\225\260\347\273\204\347\232\204\344\272\244\351\233\206II-350.js"
new file mode 100644
index 0000000..be6e139
--- /dev/null
+++ "b/\344\270\244\344\270\252\346\225\260\347\273\204\347\232\204\344\272\244\351\233\206II-350.js"
@@ -0,0 +1,36 @@
+/**
+ * @param {number[]} nums1
+ * @param {number[]} nums2
+ * @return {number[]}
+ */
+let intersect = function (nums1, nums2) {
+ let map1 = makeCountMap(nums1)
+ let map2 = makeCountMap(nums2)
+ let res = []
+ for (let num of map1.keys()) {
+ const count1 = map1.get(num)
+ const count2 = map2.get(num)
+
+ if (count2) {
+ const pushCount = Math.min(count1, count2)
+ for (let i = 0; i < pushCount; i++) {
+ res.push(num)
+ }
+ }
+ }
+ return res
+}
+
+function makeCountMap(nums) {
+ let map = new Map()
+ for (let i = 0; i < nums.length; i++) {
+ let num = nums[i]
+ let count = map.get(num)
+ if (count) {
+ map.set(num, count + 1)
+ } else {
+ map.set(num, 1)
+ }
+ }
+ return map
+}
diff --git "a/\344\272\214\345\210\206\346\237\245\346\211\276/x \347\232\204\345\271\263\346\226\271\346\240\271-69.js" "b/\344\272\214\345\210\206\346\237\245\346\211\276/x \347\232\204\345\271\263\346\226\271\346\240\271-69.js"
new file mode 100644
index 0000000..7ca5020
--- /dev/null
+++ "b/\344\272\214\345\210\206\346\237\245\346\211\276/x \347\232\204\345\271\263\346\226\271\346\240\271-69.js"
@@ -0,0 +1,25 @@
+/**
+ * @param {number} x
+ * @return {number}
+ */
+let mySqrt = function (x) {
+ let left = 0;
+ let right = x;
+ let ans = -1
+ while (left <= right) {
+ let mid = Math.round((left + right) / 2);
+ let product = mid * mid;
+ if (product < x) {
+ ans = mid
+ left = mid + 1;
+ } else if (product > x) {
+ right = mid - 1;
+ } else if (product === x) {
+ return mid;
+ }
+ }
+
+ return ans
+};
+
+console.log(mySqrt(200));
diff --git "a/\344\272\214\345\210\206\346\237\245\346\211\276/\344\272\214\345\210\206\346\237\245\346\211\276.js" "b/\344\272\214\345\210\206\346\237\245\346\211\276/\344\272\214\345\210\206\346\237\245\346\211\276.js"
new file mode 100644
index 0000000..2c29806
--- /dev/null
+++ "b/\344\272\214\345\210\206\346\237\245\346\211\276/\344\272\214\345\210\206\346\237\245\346\211\276.js"
@@ -0,0 +1,25 @@
+/**
+ * 二分搜索 从一个数组中搜索一个确定的数
+ */
+
+function binarySearch(arr, n, target) {
+ // 在[l...r]的范围里寻找target
+ let l = 0;
+ let r = n - 1;
+ while (l <= r) {
+ let mid = Math.round((l + r) / 2);
+
+ if (arr[mid] === target) {
+ return mid;
+ }
+
+ if (target > arr[mid]) {
+ l = mid + 1; // 在[mid+1...r]的范围里寻找target
+ } else {
+ r = mid - 1;
+ }
+ }
+ return -1;
+}
+
+console.log(console.log(binarySearch([1, 2, 3, 4, 5], 5, 2)));
diff --git "a/\344\272\214\345\217\211\346\240\221/\344\272\214\345\217\211\346\220\234\347\264\242\346\240\221\344\270\255\347\254\254K\345\260\217\347\232\204\345\205\203\347\264\240.js" "b/\344\272\214\345\217\211\346\240\221/\344\272\214\345\217\211\346\220\234\347\264\242\346\240\221\344\270\255\347\254\254K\345\260\217\347\232\204\345\205\203\347\264\240.js"
new file mode 100644
index 0000000..30d1ff5
--- /dev/null
+++ "b/\344\272\214\345\217\211\346\240\221/\344\272\214\345\217\211\346\220\234\347\264\242\346\240\221\344\270\255\347\254\254K\345\260\217\347\232\204\345\205\203\347\264\240.js"
@@ -0,0 +1,34 @@
+/**
+ * Definition for a binary tree node.
+ * function TreeNode(val, left, right) {
+ * this.val = (val===undefined ? 0 : val)
+ * this.left = (left===undefined ? null : left)
+ * this.right = (right===undefined ? null : right)
+ * }
+ */
+/**
+ * @param {TreeNode} root
+ * @param {number} k
+ * @return {number}
+ */
+var kthSmallest = function (root, k) {
+ let count = 0
+ let finded
+
+ let dfs = (node) => {
+ if (!node) {
+ return
+ }
+ dfs(node.left)
+ count++
+ if (count === k) {
+ finded = node.val
+ return
+ }
+ dfs(node.right)
+ }
+
+ dfs(root)
+
+ return finded
+}
diff --git "a/\344\272\214\345\217\211\346\240\221/\344\272\214\345\217\211\346\240\221\347\232\204\345\217\263\350\247\206\345\233\276-199.js" "b/\344\272\214\345\217\211\346\240\221/\344\272\214\345\217\211\346\240\221\347\232\204\345\217\263\350\247\206\345\233\276-199.js"
new file mode 100644
index 0000000..5ef8278
--- /dev/null
+++ "b/\344\272\214\345\217\211\346\240\221/\344\272\214\345\217\211\346\240\221\347\232\204\345\217\263\350\247\206\345\233\276-199.js"
@@ -0,0 +1,23 @@
+let rightSideView = function (root) {
+ if (!root) return []
+ let queue = [root]
+ let res = []
+ while (queue.length) {
+ let len = queue.length
+ let last
+ for (let i = 0; i < len; i++) {
+ let node = queue.shift()
+ if (node.left) {
+ queue.push(node.left)
+ }
+ if (node.right) {
+ queue.push(node.right)
+ }
+ if (node.val !== undefined) {
+ last = node.val
+ }
+ }
+ res.push(last)
+ }
+ return res
+}
diff --git "a/\344\272\214\345\217\211\346\240\221/\344\272\214\345\217\211\346\240\221\347\232\204\345\261\202\346\254\241\351\201\215\345\216\206 II-107.js" "b/\344\272\214\345\217\211\346\240\221/\344\272\214\345\217\211\346\240\221\347\232\204\345\261\202\346\254\241\351\201\215\345\216\206 II-107.js"
new file mode 100644
index 0000000..52ff27d
--- /dev/null
+++ "b/\344\272\214\345\217\211\346\240\221/\344\272\214\345\217\211\346\240\221\347\232\204\345\261\202\346\254\241\351\201\215\345\216\206 II-107.js"
@@ -0,0 +1,40 @@
+/**
+ * Definition for a binary tree node.
+ * function TreeNode(val) {
+ * this.val = val;
+ * this.left = this.right = null;
+ * }
+ */
+
+let TreeNode = require('../工具/二叉树.js')
+
+/**
+ * @param {TreeNode} root
+ * @return {number[][]}
+ */
+var levelOrderBottom = function (root) {
+ let res = []
+ let dfs = (node, level = 0) => {
+ if (!node) return
+
+ if (!res[level]) {
+ res[level] = []
+ }
+
+ dfs(node.left, level + 1)
+ dfs(node.right, level + 1)
+
+ res[level].push(node.val)
+ }
+
+ dfs(root)
+ return res.reverse()
+};
+
+var t = new TreeNode(3)
+t.left = new TreeNode(9)
+t.right = new TreeNode(20)
+t.right.left = new TreeNode(15)
+t.right.right = new TreeNode(7)
+
+console.log(levelOrderBottom(t))
\ No newline at end of file
diff --git "a/\344\272\214\345\217\211\346\240\221/\344\272\214\345\217\211\346\240\221\347\232\204\346\211\200\346\234\211\350\267\257\345\276\204-257.js" "b/\344\272\214\345\217\211\346\240\221/\344\272\214\345\217\211\346\240\221\347\232\204\346\211\200\346\234\211\350\267\257\345\276\204-257.js"
new file mode 100644
index 0000000..9df9927
--- /dev/null
+++ "b/\344\272\214\345\217\211\346\240\221/\344\272\214\345\217\211\346\240\221\347\232\204\346\211\200\346\234\211\350\267\257\345\276\204-257.js"
@@ -0,0 +1,18 @@
+let binaryTreePaths = function (root) {
+ let res = []
+ let dfs = (node, path = "") => {
+ if (!node) {
+ return
+ }
+
+ let newPath = path ? `${path}->${node.val}` : `${node.val}`
+ if (!node.left && !node.right) {
+ res.push(newPath)
+ }
+
+ dfs(node.left, newPath)
+ dfs(node.right, newPath)
+ }
+ dfs(root)
+ return res
+}
diff --git "a/\344\272\214\345\217\211\346\240\221/\344\272\214\345\217\211\346\240\221\347\232\204\346\234\200\345\244\247\346\267\261\345\272\246-104.js" "b/\344\272\214\345\217\211\346\240\221/\344\272\214\345\217\211\346\240\221\347\232\204\346\234\200\345\244\247\346\267\261\345\272\246-104.js"
new file mode 100644
index 0000000..285021b
--- /dev/null
+++ "b/\344\272\214\345\217\211\346\240\221/\344\272\214\345\217\211\346\240\221\347\232\204\346\234\200\345\244\247\346\267\261\345\272\246-104.js"
@@ -0,0 +1,35 @@
+/*
+ * @lc app=leetcode id=104 lang=javascript
+ *
+ * [104] Maximum Depth of Binary Tree
+ */
+
+// @lc code=start
+/**
+ * Definition for a binary tree node.
+ * function TreeNode(val, left, right) {
+ * this.val = (val===undefined ? 0 : val)
+ * this.left = (left===undefined ? null : left)
+ * this.right = (right===undefined ? null : right)
+ * }
+ */
+/**
+ * @param {TreeNode} root
+ * @return {number}
+ */
+let maxDepth = function (root) {
+ let max = 0
+ let helper = (node, depth) => {
+ if (!node) return
+ max = Math.max(max, depth)
+ if (node.left) {
+ helper(node.left, depth + 1)
+ }
+ if (node.right) {
+ helper(node.right, depth + 1)
+ }
+ }
+ helper(root, 1)
+ return max
+}
+// @lc code=end
diff --git "a/\344\272\214\345\217\211\346\240\221/\344\272\214\345\217\211\346\240\221\347\232\204\346\234\200\345\260\217\346\267\261\345\272\246-111.js" "b/\344\272\214\345\217\211\346\240\221/\344\272\214\345\217\211\346\240\221\347\232\204\346\234\200\345\260\217\346\267\261\345\272\246-111.js"
new file mode 100644
index 0000000..58ee699
--- /dev/null
+++ "b/\344\272\214\345\217\211\346\240\221/\344\272\214\345\217\211\346\240\221\347\232\204\346\234\200\345\260\217\346\267\261\345\272\246-111.js"
@@ -0,0 +1,27 @@
+let minDepth = function (root) {
+ if (!root) return 0
+
+ let depth = 0
+ let queue = [root]
+
+ while (queue.length) {
+ depth++
+ let len = queue.length
+ while (len--) {
+ let node = queue.shift()
+
+ let left = node.left
+ let right = node.right
+ if (!left && !right) {
+ return depth
+ }
+
+ if (left) {
+ queue.push(left)
+ }
+ if (right) {
+ queue.push(right)
+ }
+ }
+ }
+}
diff --git "a/\344\272\214\345\217\211\346\240\221/\344\272\214\345\217\211\346\240\221\347\232\204\346\234\200\350\277\221\345\205\254\345\205\261\347\245\226\345\205\210.js" "b/\344\272\214\345\217\211\346\240\221/\344\272\214\345\217\211\346\240\221\347\232\204\346\234\200\350\277\221\345\205\254\345\205\261\347\245\226\345\205\210.js"
new file mode 100644
index 0000000..5067d3c
--- /dev/null
+++ "b/\344\272\214\345\217\211\346\240\221/\344\272\214\345\217\211\346\240\221\347\232\204\346\234\200\350\277\221\345\205\254\345\205\261\347\245\226\345\205\210.js"
@@ -0,0 +1,57 @@
+let T = require("../工具/二叉树")
+
+let lowestCommonAncestor = function (root, p, q) {
+ let findAndCreate = (node, target, depth) => {
+ if (node !== target) {
+ let findInLeft
+ if (node.left) {
+ node.left.parent = node
+ findInLeft = findAndCreate(node.left, target, depth + 1)
+ }
+
+ if (findInLeft) {
+ return findInLeft
+ } else {
+ if (node.right) {
+ node.right.parent = node
+ return findAndCreate(node.right, target, depth + 1)
+ }
+ }
+ } else {
+ return {
+ depth,
+ node,
+ }
+ }
+ }
+
+ let findP = findAndCreate(root, p, 0) || {}
+ let findQ = findAndCreate(root, q, 0) || {}
+
+ let cur = findP.depth > findQ.depth ? findQ.node : findP.node
+
+ while (!(isAncestor(cur, p) && isAncestor(cur, q))) {
+ cur = cur.parent
+ }
+
+ return cur
+}
+
+function isAncestor(node, target) {
+ if (!node) {
+ return false
+ }
+ if (node !== target) {
+ return !!(isAncestor(node.left, target) || isAncestor(node.right, target))
+ } else {
+ return true
+ }
+}
+
+let l
+let r
+let t = new T(3)
+t.left = l = new T(5)
+t.right = r = new T(1)
+
+console.log(lowestCommonAncestor(t, l, r))
diff --git "a/\344\272\214\345\217\211\346\240\221/\345\210\240\351\231\244\344\272\214\345\217\211\346\220\234\347\264\242\346\240\221\344\270\255\347\232\204\350\212\202\347\202\271-450.js" "b/\344\272\214\345\217\211\346\240\221/\345\210\240\351\231\244\344\272\214\345\217\211\346\220\234\347\264\242\346\240\221\344\270\255\347\232\204\350\212\202\347\202\271-450.js"
new file mode 100644
index 0000000..8f96629
--- /dev/null
+++ "b/\344\272\214\345\217\211\346\240\221/\345\210\240\351\231\244\344\272\214\345\217\211\346\220\234\347\264\242\346\240\221\344\270\255\347\232\204\350\212\202\347\202\271-450.js"
@@ -0,0 +1,52 @@
+let deleteNode = function (root, key) {
+ let findNodePos = (node, key) => {
+ if (!node) {
+ return false
+ }
+ if (node.left && node.left.val === key) {
+ return {
+ parent: node,
+ pos: "left",
+ }
+ } else if (node.right && node.right.val === key) {
+ return {
+ parent: node,
+ pos: "right",
+ }
+ } else {
+ return findNodePos(node.left, key) || findNodePos(node.right, key)
+ }
+ }
+
+ let findLastLeft = (node) => {
+ if (!node.left) {
+ return node
+ }
+ return findLastLeft(node.left)
+ }
+
+ let virtual = new TreeNode()
+ virtual.left = root
+
+ let finded = findNodePos(virtual, key)
+ if (finded) {
+ let { parent, pos } = finded
+ let target = parent[pos]
+ let targetLeft = target.left
+ let targetRight = target.right
+
+ if (!targetLeft && !targetRight) {
+ parent[pos] = null
+ } else if (!targetRight) {
+ parent[pos] = targetLeft
+ } else if (!targetLeft) {
+ parent[pos] = targetRight
+ } else {
+ parent[pos] = targetRight
+ let lastLeft = findLastLeft(targetRight)
+ lastLeft.left = targetLeft
+ }
+ }
+
+ return virtual.left
+}
\ No newline at end of file
diff --git "a/\344\272\214\345\217\211\346\240\221/\345\257\271\347\247\260\344\272\214\345\217\211\346\240\221-101.js" "b/\344\272\214\345\217\211\346\240\221/\345\257\271\347\247\260\344\272\214\345\217\211\346\240\221-101.js"
new file mode 100644
index 0000000..cfef11c
--- /dev/null
+++ "b/\344\272\214\345\217\211\346\240\221/\345\257\271\347\247\260\344\272\214\345\217\211\346\240\221-101.js"
@@ -0,0 +1,28 @@
+/**
+ * Definition for a binary tree node.
+ * function TreeNode(val) {
+ * this.val = val;
+ * this.left = this.right = null;
+ * }
+ */
+/**
+ * @param {TreeNode} root
+ * @return {boolean}
+ */
+var isSymmetric = function (root) {
+ if (!root) return true
+ let helper = (left, right) => {
+ if (!left && !right) {
+ return true
+ }
+ if (!left || !right) {
+ return false
+ }
+ if (left.val === right.val) {
+ return helper(left.left, right.right) && helper(left.right, right.left)
+ } else {
+ return false
+ }
+ }
+ return helper(root, root)
+}
diff --git "a/\344\272\214\345\217\211\346\240\221/\345\260\206\346\234\211\345\272\217\346\225\260\347\273\204\350\275\254\344\270\272\344\272\214\345\217\211\346\220\234\347\264\242\346\240\221.js" "b/\344\272\214\345\217\211\346\240\221/\345\260\206\346\234\211\345\272\217\346\225\260\347\273\204\350\275\254\344\270\272\344\272\214\345\217\211\346\220\234\347\264\242\346\240\221.js"
new file mode 100644
index 0000000..8f717c4
--- /dev/null
+++ "b/\344\272\214\345\217\211\346\240\221/\345\260\206\346\234\211\345\272\217\346\225\260\347\273\204\350\275\254\344\270\272\344\272\214\345\217\211\346\220\234\347\264\242\346\240\221.js"
@@ -0,0 +1,13 @@
+let sortedArrayToBST = function (nums) {
+ let n = nums.length
+ if (!n) {
+ return null
+ }
+ let mid = Math.floor(n / 2)
+ let root = new TreeNode(nums[mid])
+
+ root.left = sortedArrayToBST(nums.slice(0, mid))
+ root.right = sortedArrayToBST(nums.slice(mid + 1, n))
+
+ return root
+};
\ No newline at end of file
diff --git "a/\344\272\214\345\217\211\346\240\221/\345\267\246\345\217\266\345\255\220\344\271\213\345\222\214-404.js" "b/\344\272\214\345\217\211\346\240\221/\345\267\246\345\217\266\345\255\220\344\271\213\345\222\214-404.js"
new file mode 100644
index 0000000..72f1a56
--- /dev/null
+++ "b/\344\272\214\345\217\211\346\240\221/\345\267\246\345\217\266\345\255\220\344\271\213\345\222\214-404.js"
@@ -0,0 +1,22 @@
+let sumOfLeftLeaves = function (root) {
+ let sum = 0
+
+ let dfs = (node) => {
+ if (!node) return
+
+ if (isLeaf(node.left)) {
+ sum += node.left.val
+ }
+
+ dfs(node.left)
+ dfs(node.right)
+ }
+
+ dfs(root)
+
+ return sum
+}
+
+function isLeaf(node) {
+ return !!node && !node.left && !node.right
+}
diff --git "a/\344\272\214\345\217\211\346\240\221/\345\271\263\350\241\241\344\272\214\345\217\211\346\240\221-110.js" "b/\344\272\214\345\217\211\346\240\221/\345\271\263\350\241\241\344\272\214\345\217\211\346\240\221-110.js"
new file mode 100644
index 0000000..9fb5be1
--- /dev/null
+++ "b/\344\272\214\345\217\211\346\240\221/\345\271\263\350\241\241\344\272\214\345\217\211\346\240\221-110.js"
@@ -0,0 +1,15 @@
+let isBalanced = function (root) {
+ if (!root) {
+ return true
+ }
+
+ let isSonBalnaced =
+ Math.abs(getHeight(root.left) - getHeight(root.right)) <= 1
+
+ return isSonBalnaced && isBalanced(root.left) && isBalanced(root.right)
+}
+
+function getHeight(node) {
+ if (!node) return 0
+ return Math.max(getHeight(node.left), getHeight(node.right)) + 1
+}
diff --git "a/\344\272\214\345\217\211\346\240\221/\346\261\202\346\240\271\345\210\260\345\217\266\345\255\220\350\212\202\347\202\271\346\225\260\345\255\227\344\271\213\345\222\214-129.js" "b/\344\272\214\345\217\211\346\240\221/\346\261\202\346\240\271\345\210\260\345\217\266\345\255\220\350\212\202\347\202\271\346\225\260\345\255\227\344\271\213\345\222\214-129.js"
new file mode 100644
index 0000000..9695144
--- /dev/null
+++ "b/\344\272\214\345\217\211\346\240\221/\346\261\202\346\240\271\345\210\260\345\217\266\345\255\220\350\212\202\347\202\271\346\225\260\345\255\227\344\271\213\345\222\214-129.js"
@@ -0,0 +1,23 @@
+let sumNumbers = function (root) {
+ let paths = []
+
+ let dfs = (node, path) => {
+ if (!node) {
+ return
+ }
+
+ let newPath = `${path}${node.val}`
+ if (!node.left && !node.right) {
+ paths.push(newPath)
+ return
+ }
+
+ dfs(node.left, newPath)
+ dfs(node.right, newPath)
+ }
+
+ dfs(root, "")
+ return paths.reduce((total, val) => {
+ return total + Number(val)
+ }, 0)
+}
diff --git "a/\344\272\214\345\217\211\346\240\221/\350\267\257\345\276\204\346\200\273\345\222\214 II-113.js" "b/\344\272\214\345\217\211\346\240\221/\350\267\257\345\276\204\346\200\273\345\222\214 II-113.js"
new file mode 100644
index 0000000..5055984
--- /dev/null
+++ "b/\344\272\214\345\217\211\346\240\221/\350\267\257\345\276\204\346\200\273\345\222\214 II-113.js"
@@ -0,0 +1,45 @@
+let TreeNode = require('../工具/二叉树.js')
+
+var pathSum = function (root, sum) {
+ let res = [];
+ let search = function (node, paths) {
+ if (!node.val) return
+ paths.push(node.val);
+ if (node.left) {
+ search(node.left, paths);
+ }
+ if (node.right) {
+ search(node.right, paths);
+ }
+ if (!node.left && !node.right) {
+ if (sumVals(paths) === sum) {
+ res.push(paths.slice());
+ }
+ }
+ paths.pop();
+ };
+ search(root, []);
+ return res;
+};
+
+function sumVals(nodes) {
+ return nodes.reduce((prev, val) => {
+ prev += val;
+ return prev;
+ }, 0);
+}
+
+
+var t = new TreeNode(5)
+t.left = new TreeNode(4)
+t.left.left = new TreeNode(11)
+t.left.left.left = new TreeNode(7)
+t.left.left.right = new TreeNode(2)
+
+t.right = new TreeNode(8)
+t.right.left = new TreeNode(13)
+t.right.right = new TreeNode(4)
+t.right.right.left = new TreeNode(5)
+t.right.right.right = new TreeNode(1)
+
+console.log(pathSum(new TreeNode(), 22))
diff --git "a/\344\272\214\345\217\211\346\240\221/\350\267\257\345\276\204\346\200\273\345\222\214 III-437.js" "b/\344\272\214\345\217\211\346\240\221/\350\267\257\345\276\204\346\200\273\345\222\214 III-437.js"
new file mode 100644
index 0000000..40faec2
--- /dev/null
+++ "b/\344\272\214\345\217\211\346\240\221/\350\267\257\345\276\204\346\200\273\345\222\214 III-437.js"
@@ -0,0 +1,22 @@
+let pathSum = function (root, sum) {
+ if (!root) return 0
+ return (
+ countSum(root, sum) + pathSum(root.left, sum) + pathSum(root.right, sum)
+ )
+}
+
+let countSum = (node, sum) => {
+ let count = 0
+ let dfs = (node, target) => {
+ if (!node) return
+
+ if (node.val === target) {
+ count += 1
+ }
+
+ dfs(node.left, target - node.val)
+ dfs(node.right, target - node.val)
+ }
+ dfs(node, sum)
+ return count
+}
diff --git "a/\344\272\214\345\217\211\346\240\221/\350\267\257\345\276\204\346\200\273\345\222\214-112.js" "b/\344\272\214\345\217\211\346\240\221/\350\267\257\345\276\204\346\200\273\345\222\214-112.js"
new file mode 100644
index 0000000..753b265
--- /dev/null
+++ "b/\344\272\214\345\217\211\346\240\221/\350\267\257\345\276\204\346\200\273\345\222\214-112.js"
@@ -0,0 +1,14 @@
+let hasPathSum = function (root, sum) {
+ if (!root) {
+ return false
+ }
+ // 叶子节点 判断当前的值是否等于 sum 即可
+ if (!root.left && !root.right) {
+ return root.val === sum
+ }
+
+ return (
+ hasPathSum(root.left, sum - root.val) ||
+ hasPathSum(root.right, sum - root.val)
+ )
+}
diff --git "a/\347\256\227\346\263\225/\344\272\214\345\217\211\346\240\221\347\232\204\345\211\215\344\270\255\345\220\216\345\272\217\351\201\215\345\216\206.js" "b/\344\272\214\345\217\211\346\240\221\347\232\204\345\211\215\344\270\255\345\220\216\345\272\217\351\201\215\345\216\206.js"
similarity index 100%
rename from "\347\256\227\346\263\225/\344\272\214\345\217\211\346\240\221\347\232\204\345\211\215\344\270\255\345\220\216\345\272\217\351\201\215\345\216\206.js"
rename to "\344\272\214\345\217\211\346\240\221\347\232\204\345\211\215\344\270\255\345\220\216\345\272\217\351\201\215\345\216\206.js"
diff --git "a/\344\275\215\350\277\220\347\256\227/\346\211\276\344\270\215\345\220\214-389.js" "b/\344\275\215\350\277\220\347\256\227/\346\211\276\344\270\215\345\220\214-389.js"
new file mode 100644
index 0000000..f21e453
--- /dev/null
+++ "b/\344\275\215\350\277\220\347\256\227/\346\211\276\344\270\215\345\220\214-389.js"
@@ -0,0 +1,15 @@
+/**
+ * @param {string} s
+ * @param {string} t
+ * @return {character}
+ */
+let findTheDifference = function (s, t) {
+ let rest = t.charCodeAt(t.length - 1)
+ for (let i = 0; i < s.length; i++) {
+ let charS = s[i]
+ let charT = t[i]
+ rest ^= charS.charCodeAt(0)
+ rest ^= charT.charCodeAt(0)
+ }
+ return String.fromCharCode(rest)
+}
diff --git "a/\347\256\227\346\263\225/\345\211\215K\344\270\252\351\253\230\351\242\221\345\205\203\347\264\240.js" "b/\345\211\215K\344\270\252\351\253\230\351\242\221\345\205\203\347\264\240.js"
similarity index 71%
rename from "\347\256\227\346\263\225/\345\211\215K\344\270\252\351\253\230\351\242\221\345\205\203\347\264\240.js"
rename to "\345\211\215K\344\270\252\351\253\230\351\242\221\345\205\203\347\264\240.js"
index e6c0092..41339aa 100644
--- "a/\347\256\227\346\263\225/\345\211\215K\344\270\252\351\253\230\351\242\221\345\205\203\347\264\240.js"
+++ "b/\345\211\215K\344\270\252\351\253\230\351\242\221\345\205\203\347\264\240.js"
@@ -17,20 +17,20 @@
你的算法的时间复杂度必须优于 O(n log n) , n 是数组的大小。
*/
-var topKFrequent = function(nums, k) {
- var map = new Map()
- for (var i = 0; i < nums.length; i++) {
- var num = nums[i]
- var count = map.get(num)
+let topKFrequent = function(nums, k) {
+ let map = new Map()
+ for (let i = 0; i < nums.length; i++) {
+ let num = nums[i]
+ let count = map.get(num)
if (!count) {
map.set(num, 1)
} else {
map.set(num, count + 1)
}
}
- var sorted = Array.from(map.entries()).sort((a, b) => b[1] - a[1])
- var result = []
- for (var i = 0; i < k; i++) {
+ let sorted = Array.from(map.entries()).sort((a, b) => b[1] - a[1])
+ let result = []
+ for (let i = 0; i < k; i++) {
result.push(sorted[i][0])
}
return result
diff --git "a/\345\212\250\346\200\201\350\247\204\345\210\222/01\350\203\214\345\214\205-DP\347\211\210.js" "b/\345\212\250\346\200\201\350\247\204\345\210\222/01\350\203\214\345\214\205-DP\347\211\210.js"
new file mode 100644
index 0000000..155c545
--- /dev/null
+++ "b/\345\212\250\346\200\201\350\247\204\345\210\222/01\350\203\214\345\214\205-DP\347\211\210.js"
@@ -0,0 +1,43 @@
+/**
+ *
+ * @param {number[]} w 物品的重量集合
+ * @param {number[]} v 物品的价值集合
+ * @param {number} C 背包容量
+ */
+let knapsack01 = function (w, v, C) {
+ let n = w.length;
+ if (n === 0) return 0;
+
+ // 构建二维数组dp表
+ // x轴代表背包容量 y轴代表考虑的物品情况
+ // 第一行只考虑一种物品(基准情况)
+ // 第二行考虑一和二两种(通过拿取二和不拿二,再去组合第一行的最佳情况来求最大值)
+ // 第三行以此类推
+ let memo = new Array(n);
+ for (let i = 0; i < memo.length; i++) {
+ memo[i] = new Array(C + 1).fill(0);
+ }
+
+ // 基础情况 背包在各个容量的情况下 只考虑第一个物品时的最优解
+ for (let j = 0; j <= C; j++) {
+ memo[0][j] = j >= w[0] ? v[0] : 0;
+ }
+
+ for (let i = 1; i < n; i++) {
+ for (let j = 0; j <= C; j++) {
+ let weight = w[i];
+ let restWeight = j - weight;
+ // 有足够容量的情况下 选择当前的的物品 并且用剩余的重量去找前面几个物品组合的最优解
+ let pickNow = j >= weight ? v[i] + memo[i - 1][restWeight] : 0;
+
+ // 另一种选择 这个物品不放进背包了 直接求用这个背包容量组合前面几种物品的最优解
+ let pickPrev = memo[i - 1][j];
+
+ memo[i][j] = Math.max(pickNow, pickPrev);
+ }
+ }
+
+ return memo[n - 1][C];
+};
+
+console.log(knapsack01([1, 2, 3], [6, 10, 12], 5));
diff --git "a/\345\212\250\346\200\201\350\247\204\345\210\222/01\350\203\214\345\214\205-\351\200\222\345\275\222\347\211\210.js" "b/\345\212\250\346\200\201\350\247\204\345\210\222/01\350\203\214\345\214\205-\351\200\222\345\275\222\347\211\210.js"
new file mode 100644
index 0000000..d668e90
--- /dev/null
+++ "b/\345\212\250\346\200\201\350\247\204\345\210\222/01\350\203\214\345\214\205-\351\200\222\345\275\222\347\211\210.js"
@@ -0,0 +1,33 @@
+/**
+ *
+ * @param {number[]} w 物品的重量集合
+ * @param {number[]} v 物品的价值集合
+ * @param {number} C 背包容量
+ */
+function knapsack01(w, v, C) {
+ let n = w.length - 1;
+
+ return bestValue(w, v, n, C);
+}
+
+// 用 [0...index] 的物品
+// 填充容积为c的背包的最大价值
+function bestValue(w, v, index, c) {
+ if (index < 0 || c <= 0) return 0;
+
+ let max = bestValue(w, v, index - 1, c);
+
+ // 装背包之前需要先判断这个当前背包还可以容纳下这个物品
+ if (c >= w[index]) {
+ max = Math.max(
+ // 不装进背包
+ max,
+ // 装进背包
+ v[index] + bestValue(w, v, index - 1, c - w[index])
+ );
+ }
+
+ return max;
+}
+
+console.log(knapsack01([1, 2, 3], [6, 10, 12], 5));
diff --git "a/\345\212\250\346\200\201\350\247\204\345\210\222/\344\270\200\345\222\214\351\233\266-474.js" "b/\345\212\250\346\200\201\350\247\204\345\210\222/\344\270\200\345\222\214\351\233\266-474.js"
new file mode 100644
index 0000000..69f703a
--- /dev/null
+++ "b/\345\212\250\346\200\201\350\247\204\345\210\222/\344\270\200\345\222\214\351\233\266-474.js"
@@ -0,0 +1,49 @@
+/**
+ * @param {string[]} strs
+ * @param {number} m
+ * @param {number} n
+ * @return {number}
+ */
+let findMaxForm = function (strs, m, n) {
+ let sl = strs.length
+ if (!sl) {
+ return 0
+ }
+
+ let dp = []
+
+ for (let i = 0; i <= m; i++) {
+ dp[i] = []
+ for (let j = 0; j <= n; j++) {
+ dp[i][j] = []
+ for (let s = 0; s < sl; s++) {
+ let str = strs[s]
+ let [strM, strN] = countMAndN(str)
+
+ let pickOnlyPrev = dp[i][j][s - 1] || 0
+ let pickCurAndPrev = 0
+ if (i >= strM && j >= strN) {
+ pickCurAndPrev = 1 + (dp[i - strM][j - strN][s - 1] || 0)
+ }
+
+ dp[i][j][s] = Math.max(pickCurAndPrev, pickOnlyPrev)
+ }
+ }
+ }
+ return dp[m][n][sl - 1]
+}
+
+function countMAndN(str) {
+ let m = 0
+ let n = 0
+ for (let i = 0; i < str.length; i++) {
+ if (str[i] === "0") {
+ m++
+ } else {
+ n++
+ }
+ }
+ return [m, n]
+}
+
+console.log(findMaxForm(["10", "0", "1"], 1, 1))
diff --git "a/\345\212\250\346\200\201\350\247\204\345\210\222/\344\270\211\350\247\222\345\275\242\347\232\204\346\234\200\345\260\217\350\267\257\345\276\204\345\222\214-120.js" "b/\345\212\250\346\200\201\350\247\204\345\210\222/\344\270\211\350\247\222\345\275\242\347\232\204\346\234\200\345\260\217\350\267\257\345\276\204\345\222\214-120.js"
new file mode 100644
index 0000000..b802d89
--- /dev/null
+++ "b/\345\212\250\346\200\201\350\247\204\345\210\222/\344\270\211\350\247\222\345\275\242\347\232\204\346\234\200\345\260\217\350\267\257\345\276\204\345\222\214-120.js"
@@ -0,0 +1,28 @@
+/**
+ * @param {number[][]} triangle
+ * @return {number}
+ */
+let minimumTotal = function (triangle) {
+ let tryMin = (level, lastIndex, prevSum) => {
+ if (level === triangle.length) {
+ return prevSum
+ }
+
+ let row = triangle[level]
+ let cur = row[lastIndex]
+ let curNext = row[lastIndex + 1]
+
+ let selected = tryMin(level + 1, lastIndex, prevSum + cur)
+ if (curNext !== undefined) {
+ selected = Math.min(
+ selected,
+ tryMin(level + 1, lastIndex + 1, prevSum + curNext)
+ )
+ }
+ return selected
+ }
+
+ return tryMin(0, 0, 0)
+}
+
+minimumTotal([[2], [3, 4], [6, 5, 7], [4, 1, 8, 3]])
diff --git "a/\345\212\250\346\200\201\350\247\204\345\210\222/\344\270\213\351\231\215\350\267\257\345\276\204\346\234\200\345\260\217\345\222\214-931.js" "b/\345\212\250\346\200\201\350\247\204\345\210\222/\344\270\213\351\231\215\350\267\257\345\276\204\346\234\200\345\260\217\345\222\214-931.js"
new file mode 100644
index 0000000..30ef633
--- /dev/null
+++ "b/\345\212\250\346\200\201\350\247\204\345\210\222/\344\270\213\351\231\215\350\267\257\345\276\204\346\234\200\345\260\217\345\222\214-931.js"
@@ -0,0 +1,34 @@
+/**
+ * @param {number[][]} A
+ * @return {number}
+ */
+let minFallingPathSum = function (A) {
+ let n = A.length
+
+ let dp = []
+ for (let i = 0; i < n; i++) {
+ dp[i] = []
+ }
+
+ for (let j = 0; j < n; j++) {
+ dp[n - 1][j] = A[n - 1][j]
+ }
+
+ for (let i = n - 2; i >= 0; i--) {
+ for (let j = 0; j < n; j++) {
+ dp[i][j] = Infinity
+ let left = j - 1
+ let right = j + 1
+ let mid = j
+ let nextRowIndexes = [left, mid, right]
+ for (let nextRowIndex of nextRowIndexes) {
+ if (nextRowIndex >= 0 && nextRowIndex < n) {
+ dp[i][j] = Math.min(dp[i][j], A[i][j] + dp[i + 1][nextRowIndex])
+ }
+ }
+ }
+ }
+
+ // 第一行的最小值 可以确定整体的最小路径
+ return Math.min(...dp[0])
+}
diff --git "a/\345\212\250\346\200\201\350\247\204\345\210\222/\344\271\230\347\247\257\346\234\200\345\244\247\345\255\220\346\225\260\347\273\204-152.js" "b/\345\212\250\346\200\201\350\247\204\345\210\222/\344\271\230\347\247\257\346\234\200\345\244\247\345\255\220\346\225\260\347\273\204-152.js"
new file mode 100644
index 0000000..6fa45df
--- /dev/null
+++ "b/\345\212\250\346\200\201\350\247\204\345\210\222/\344\271\230\347\247\257\346\234\200\345\244\247\345\255\220\346\225\260\347\273\204-152.js"
@@ -0,0 +1,23 @@
+let maxProduct = function (nums) {
+ let dp = [];
+ let n = nums.length;
+
+ let last = nums[n - 1];
+ dp[n - 1] = {
+ max: last,
+ min: last,
+ };
+
+ for (i = nums.length - 2; i >= 0; i--) {
+ let num = nums[i];
+ let withNextMin = num * dp[i + 1].min;
+ let withNextMax = num * dp[i + 1].max;
+ let withoutNext = num;
+ dp[i] = {
+ max: Math.max(withoutNext, withNextMin, withNextMax),
+ min: Math.min(withoutNext, withNextMin, withNextMax),
+ };
+ }
+
+ return Math.max(...dp.map(({ max }) => max));
+};
diff --git "a/\345\212\250\346\200\201\350\247\204\345\210\222/\344\271\260\345\215\226\350\202\241\347\245\250\347\232\204\346\234\200\344\275\263\346\227\266\346\234\272.js" "b/\345\212\250\346\200\201\350\247\204\345\210\222/\344\271\260\345\215\226\350\202\241\347\245\250\347\232\204\346\234\200\344\275\263\346\227\266\346\234\272.js"
new file mode 100644
index 0000000..5c5d751
--- /dev/null
+++ "b/\345\212\250\346\200\201\350\247\204\345\210\222/\344\271\260\345\215\226\350\202\241\347\245\250\347\232\204\346\234\200\344\275\263\346\227\266\346\234\272.js"
@@ -0,0 +1,44 @@
+
+
+/**
+ * 循环版
+ * @param {number[]} prices
+ * @return {number}
+ */
+let maxProfit = function(prices) {
+ let max = 0
+ for (let i = 1; i < prices.length; i++) {
+ for (let j = 0; j < i; j++) {
+ let price = prices[j]
+ let sale = prices[i] - price
+ max = Math.max(max, sale)
+ }
+ }
+
+ return max
+};
+
+
+/**
+ * DP版
+ */
+let maxProfit = function (prices) {
+ let n = prices.length
+ if (!n || n === 1) return 0
+
+ // 最大收益
+ let prevMax = 0
+ // 最小价格
+ let prevMin = prices[0]
+
+ for (let i = 1; i < n; i++) {
+ let price = prices[i]
+
+ prevMax = Math.max(price - prevMin, prevMax)
+ prevMin = Math.min(price, prevMin)
+ }
+
+ return prevMax
+};
+
+console.log(maxProfit([1, 2]))
\ No newline at end of file
diff --git "a/\345\212\250\346\200\201\350\247\204\345\210\222/\344\275\277\347\224\250\346\234\200\345\260\217\350\212\261\350\264\271\347\210\254\346\245\274\346\242\257-746.js" "b/\345\212\250\346\200\201\350\247\204\345\210\222/\344\275\277\347\224\250\346\234\200\345\260\217\350\212\261\350\264\271\347\210\254\346\245\274\346\242\257-746.js"
new file mode 100644
index 0000000..59f9997
--- /dev/null
+++ "b/\345\212\250\346\200\201\350\247\204\345\210\222/\344\275\277\347\224\250\346\234\200\345\260\217\350\212\261\350\264\271\347\210\254\346\245\274\346\242\257-746.js"
@@ -0,0 +1,16 @@
+/**
+ * @param {number[]} cost
+ * @return {number}
+ */
+let minCostClimbingStairs = function (cost) {
+ let dp = [];
+
+ for (let i = cost.length - 1; i >= 0; i--) {
+ let oneStep = cost[i] + (dp[i + 1] || 0);
+ let twoStep = cost[i] + (dp[i + 2] || 0);
+
+ dp[i] = Math.min(oneStep, twoStep);
+ }
+
+ return Math.min(dp[0], dp[1]);
+};
\ No newline at end of file
diff --git "a/\345\212\250\346\200\201\350\247\204\345\210\222/\345\210\206\345\211\262\347\255\211\345\222\214\345\255\220\351\233\206-416.js" "b/\345\212\250\346\200\201\350\247\204\345\210\222/\345\210\206\345\211\262\347\255\211\345\222\214\345\255\220\351\233\206-416.js"
new file mode 100644
index 0000000..b7f5fe0
--- /dev/null
+++ "b/\345\212\250\346\200\201\350\247\204\345\210\222/\345\210\206\345\211\262\347\255\211\345\222\214\345\255\220\351\233\206-416.js"
@@ -0,0 +1,51 @@
+/**
+ * @param {number[]} nums
+ * @return {boolean}
+ */
+let canPartition = function (nums) {
+ let n = nums.length
+
+ let sum = nums.reduce((a, b) => a + b);
+
+ let target = sum / 2;
+
+ // 数据不是整数 直接return
+ if (Math.ceil(target) !== target) {
+ return false;
+ }
+
+ let dp = new Array(n);
+ for (let i = 0; i < dp.length; i++) {
+ dp[i] = new Array(target + 1).fill(false);
+ }
+
+ // 列代表可以选择去凑数的数值
+ for (let i = 0; i < dp.length; i++) {
+ // 行代表是否可以凑到这个数字j
+ for (let j = 0; j <= target; j++) {
+ // 不用当前数,直接选择前一行的结果
+ let pickPrev = (dp[i - 1] ? dp[i - 1][j]: false) || false
+
+ // 拿出当前数,并且从前一行里找其他的值能否凑成剩下的值
+ let pickCurrentAndPrev = (dp[i - 1] ? dp[i - 1][j - nums[i]]: false) || false
+
+ // 只拿的值直接去凑目标值
+ let pickCurrent = j === nums[i]
+
+ // 任意一者满足 即可理解成 「i下标的值」配合「i下标之前的数值」 可以一起凑成目标值
+ let can = (
+ pickPrev ||
+ pickCurrent||
+ pickCurrentAndPrev
+ )
+
+ dp[i][j] = can
+
+ // 只要任意一行的 target 列满足条件 即可认为有「子数组」可以凑成目标值 直接返回 true
+ if ((j === target) && can) {
+ return true
+ }
+ }
+ }
+ return dp[n - 1][target]
+};
\ No newline at end of file
diff --git "a/\345\212\250\346\200\201\350\247\204\345\210\222/\345\215\225\350\257\215\346\213\206\345\210\206 II.js" "b/\345\212\250\346\200\201\350\247\204\345\210\222/\345\215\225\350\257\215\346\213\206\345\210\206 II.js"
new file mode 100644
index 0000000..06c432a
--- /dev/null
+++ "b/\345\212\250\346\200\201\350\247\204\345\210\222/\345\215\225\350\257\215\346\213\206\345\210\206 II.js"
@@ -0,0 +1,37 @@
+let wordBreak = function (s, wordDict) {
+ let uniqSChars = uniq(s.split(""))
+ let uniqWordDictChars = uniq(wordDict.join(""))
+ if (uniqSChars.length !== uniqWordDictChars.length) {
+ return false
+ }
+
+ let n = s.length
+ if (!n) {
+ return []
+ }
+
+ let wordSet = new Set(wordDict)
+ let dp = []
+ dp[0] = [""]
+
+ for (let i = 1; i <= n; i++) {
+ let res = []
+ for (let j = i; j >= 0; j--) {
+ let word = s.slice(j, i)
+ if (wordSet.has(word)) {
+ if (dp[j] && dp[j].length) {
+ for (let prev of dp[j]) {
+ res.push(prev ? prev + " " + word : word)
+ }
+ }
+ }
+ }
+ dp[i] = res
+ }
+
+ return dp[n]
+}
+
+function uniq(arr) {
+ return Array.from(new Set(arr))
+}
diff --git "a/\345\212\250\346\200\201\350\247\204\345\210\222/\345\215\225\350\257\215\346\213\206\345\210\206-139.js" "b/\345\212\250\346\200\201\350\247\204\345\210\222/\345\215\225\350\257\215\346\213\206\345\210\206-139.js"
new file mode 100644
index 0000000..dbb4672
--- /dev/null
+++ "b/\345\212\250\346\200\201\350\247\204\345\210\222/\345\215\225\350\257\215\346\213\206\345\210\206-139.js"
@@ -0,0 +1,25 @@
+/**
+ * @param {string} s
+ * @param {string[]} wordDict
+ * @return {boolean}
+ */
+let wordBreak = function (s, wordDict) {
+ let n = s.length
+ if (!n) return true
+
+ let wordSet = new Set(wordDict)
+ let dp = []
+ dp[0] = true
+
+ for (let i = 0; i <= n; i++) {
+ for (let j = i; j >= 0; j--) {
+ let word = s.slice(j, i)
+ if (wordSet.has(word) && dp[j]) {
+ dp[i] = true
+ break
+ }
+ }
+ }
+
+ return !!dp[n]
+}
diff --git "a/\345\212\250\346\200\201\350\247\204\345\210\222/\345\217\257\350\216\267\345\276\227\347\232\204\346\234\200\345\244\247\347\202\271\346\225\260-1423.js" "b/\345\212\250\346\200\201\350\247\204\345\210\222/\345\217\257\350\216\267\345\276\227\347\232\204\346\234\200\345\244\247\347\202\271\346\225\260-1423.js"
new file mode 100644
index 0000000..12a63d3
--- /dev/null
+++ "b/\345\212\250\346\200\201\350\247\204\345\210\222/\345\217\257\350\216\267\345\276\227\347\232\204\346\234\200\345\244\247\347\202\271\346\225\260-1423.js"
@@ -0,0 +1,45 @@
+// 力扣超时 卡在第26个用例
+let maxScore = function (cardPoints, k) {
+ let n = cardPoints.length
+
+ let prevTimeChunk = []
+ for (let i = 0; i < n; i++) {
+ for (let j = i; j < n; j++) {
+ if (!prevTimeChunk[i]) {
+ prevTimeChunk[i] = []
+ }
+ prevTimeChunk[i][j] = 0
+ }
+ }
+
+ let currentTimeChunk = []
+
+ for (let time = 1; time <= k; time++) {
+ for (let i = n - 1; i >= 0; i--) {
+ for (let j = i; j < n; j++) {
+ if (!currentTimeChunk[i]) {
+ currentTimeChunk[i] = []
+ }
+
+ // 只剩一个可选 有次数的情况下就选这一项 否则为0
+ if (i === j) {
+ currentTimeChunk[i][j] = time > 0 ? cardPoints[i] : 0
+ }
+
+ let pickHead = cardPoints[i]
+ let pickTail = cardPoints[j]
+
+ currentTimeChunk[i][j] = Math.max(
+ pickHead + (prevTimeChunk[i + 1] ? prevTimeChunk[i + 1][j] || 0 : 0),
+ pickTail + (prevTimeChunk[i][j - 1] || 0)
+ )
+ }
+ }
+ prevTimeChunk = currentTimeChunk
+ currentTimeChunk = []
+ }
+
+ return prevTimeChunk[0][n - 1]
+}
+
+console.log(maxScore([1,79,80,1,1,1,200,1], 3))
diff --git "a/\345\212\250\346\200\201\350\247\204\345\210\222/\345\256\214\345\205\250\345\271\263\346\226\271\346\225\260-279.js" "b/\345\212\250\346\200\201\350\247\204\345\210\222/\345\256\214\345\205\250\345\271\263\346\226\271\346\225\260-279.js"
new file mode 100644
index 0000000..35c760f
--- /dev/null
+++ "b/\345\212\250\346\200\201\350\247\204\345\210\222/\345\256\214\345\205\250\345\271\263\346\226\271\346\225\260-279.js"
@@ -0,0 +1,33 @@
+// https://github.com/sl1673495/leetcode-javascript/issues/9
+
+/**
+ * @param {number} n
+ * @return {number}
+ */
+let numSquares = function (n) {
+ let dp = [];
+
+ // 求0就假设为0次
+ dp[0] = 0;
+
+ for (let i = 1; i <= n; i++) {
+ let j = 1;
+ // 初始化为Infinity 这样后面任意一个小值都可以覆盖它
+ let min = Infinity;
+ while (true) {
+ // 用 i 减去不断递增的平方数 j * j
+ let prev = i - j * j;
+ if (prev < 0) {
+ break;
+ }
+
+ // 假设i = 10、j = 1 实际上就是在求dp[10 - 1] + 1
+ // 也就是凑成 9 的最小次数 再加上 1(也就是 1 这个平方数的次数)
+ min = Math.min(min, dp[prev] + 1);
+ j++;
+ }
+ dp[i] = min === Infinity ? 0 : min;
+ }
+
+ return dp[n];
+};
diff --git "a/\345\212\250\346\200\201\350\247\204\345\210\222/\346\201\242\345\244\215\347\251\272\346\240\274-\351\235\242\350\257\225\351\242\230 17.13.js" "b/\345\212\250\346\200\201\350\247\204\345\210\222/\346\201\242\345\244\215\347\251\272\346\240\274-\351\235\242\350\257\225\351\242\230 17.13.js"
new file mode 100644
index 0000000..676d151
--- /dev/null
+++ "b/\345\212\250\346\200\201\350\247\204\345\210\222/\346\201\242\345\244\215\347\251\272\346\240\274-\351\235\242\350\257\225\351\242\230 17.13.js"
@@ -0,0 +1,19 @@
+/**
+ * @param {string[]} dictionary
+ * @param {string} sentence
+ * @return {number}
+ */
+let respace = function (dictionary, sentence) {
+ let n = sentence.length
+ let dp = [0]
+ for (let i = 1; i <= n; i++) {
+ let min = dp[i - 1] + 1
+ for (let word of dictionary) {
+ if (sentence.substring(i - word.length, i) === word) {
+ min = Math.min(min, dp[i - word.length])
+ }
+ }
+ dp[i] = min
+ }
+ return dp[n]
+}
diff --git "a/\345\212\250\346\200\201\350\247\204\345\210\222/\346\211\223\345\256\266\345\212\253\350\210\215-198.js" "b/\345\212\250\346\200\201\350\247\204\345\210\222/\346\211\223\345\256\266\345\212\253\350\210\215-198.js"
new file mode 100644
index 0000000..17c64e8
--- /dev/null
+++ "b/\345\212\250\346\200\201\350\247\204\345\210\222/\346\211\223\345\256\266\345\212\253\350\210\215-198.js"
@@ -0,0 +1,117 @@
+let assert = require("assert");
+
+/**
+ * 打家劫舍 递归版
+ * @param {number[]} nums
+ * @return {number}
+ */
+let robRecurision = function (nums) {
+ // 考虑从 index 开始到 nums - 1 为止
+ // 打劫的最高价值
+ let tryRob = function (nums, index) {
+ // 超出边界了
+ if (index >= nums.length) {
+ return 0;
+ }
+
+ let max = 0;
+ // 从 index,...n 分别选作起点开始抢劫
+ // 求出各个值作为起点的最优解
+ for (let i = index; i < nums.length; i++) {
+ let value = nums[i];
+
+ // 不能打劫邻舍 所以要 +2
+ max = Math.max(max, value + tryRob(nums, i + 2));
+ }
+
+ return max;
+ };
+
+ return tryRob(nums, 0);
+};
+
+assert(robRecurision([1, 2, 3, 1]) === 4);
+assert(robRecurision([2, 7, 9, 3, 1]) === 12);
+
+/**
+ * 打家劫舍-递归版2
+ * 把打劫细分为
+ *
+ * 1. 打劫当前房子 那么下次就要从start + 2开始
+ * 2. 打劫下一个房子 那么就直接从start + 1开始
+ *
+ * 求这两者间的最大值
+ * @param {*} nums
+ */
+let robRecurision2 = function (nums) {
+ let memo = [];
+ function tryRob(nums, start) {
+ let memorized = memo[start];
+ if (memorized) return memorized;
+
+ if (start > nums.length - 1) return 0;
+
+ let robNow = nums[start] + tryRob(nums, start + 2);
+ let robNext = tryRob(nums, start + 1);
+
+ let best = Math.max(robNext, robNow);
+ memo[start] = best;
+
+ return best;
+ }
+
+ return tryRob(nums, 0);
+};
+
+assert(robRecurision2([1, 2, 3, 1]) === 4);
+assert(robRecurision2([2, 7, 9, 3, 1]) === 12);
+
+/**
+ * 打家劫舍 DP版
+ * @param {number[]} nums
+ * @return {number}
+ */
+let rob = function (nums) {
+ if (!nums.length) {
+ return 0;
+ }
+ let dp = [];
+
+ for (let i = nums.length - 1; i >= 0; i--) {
+ let max = 0;
+ for (let index = i; index < nums.length; index++) {
+ let value = nums[index];
+ max = Math.max(max, value + (dp[index + 2] || 0));
+ }
+ dp[i] = max;
+ }
+
+ return dp[0];
+};
+
+assert(rob([1, 2, 3, 1]) === 4);
+assert(rob([2, 7, 9, 3, 1]) === 12);
+
+/**
+ * 打家劫舍 DP版2
+ * @param {number[]} nums
+ * @return {number}
+ */
+let rob2 = function (nums) {
+ if (!nums.length) {
+ return 0;
+ }
+ let dp = [];
+
+ for (let i = nums.length - 1; i >= 0; i--) {
+ let robNow = nums[i] + (dp[i + 2] || 0)
+ let robNext = dp[i + 1] || 0
+
+ dp[i] = Math.max(robNow, robNext)
+ }
+
+ return dp[0];
+};
+
+
+console.log(rob2([1, 10, 3, 1, 5]));
diff --git "a/\345\212\250\346\200\201\350\247\204\345\210\222/\346\211\223\345\256\266\345\212\253\350\210\215III-337.js" "b/\345\212\250\346\200\201\350\247\204\345\210\222/\346\211\223\345\256\266\345\212\253\350\210\215III-337.js"
new file mode 100644
index 0000000..af183a9
--- /dev/null
+++ "b/\345\212\250\346\200\201\350\247\204\345\210\222/\346\211\223\345\256\266\345\212\253\350\210\215III-337.js"
@@ -0,0 +1,51 @@
+/**
+ * Definition for a binary tree node.
+ * function TreeNode(val) {
+ * this.val = val;
+ * this.left = this.right = null;
+ * }
+ */
+const TreeNode = require("../工具/二叉树");
+
+/**
+ * 65 / 124 个通过测试用例
+ */
+
+/**
+ * @param {TreeNode} root
+ * @return {number}
+ */
+/**
+ * @param {TreeNode} root
+ * @return {number}
+ */
+let memo = new WeakMap()
+let rob = function (root) {
+ if (!root) {
+ return 0;
+ }
+
+ let memorized = memo.get(root)
+ if (memorized) {
+ return memorized
+ }
+
+ let notRob = rob(root.left) + rob(root.right);
+ let robNow =
+ (root.val || 0) +
+ (root.left ? rob(root.left.left) + rob(root.left.right) : 0) +
+ (root.right ? rob(root.right.left) + rob(root.right.right) : 0);
+
+ let max = Math.max(notRob, robNow);
+ memo.set(root, max)
+ return max;
+};
+
+// 这种情况是不对的 应该计算出7
+let tree1 = new TreeNode(2);
+tree1.left = new TreeNode(1);
+tree1.right = new TreeNode(3);
+tree1.left.left = new TreeNode(null);
+tree1.left.right = new TreeNode(4);
+
+console.log(rob(tree1));
diff --git "a/\345\212\250\346\200\201\350\247\204\345\210\222/\346\211\276\347\241\254\345\270\201-\345\212\250\346\200\201\350\247\204\345\210\222\347\211\210.js" "b/\345\212\250\346\200\201\350\247\204\345\210\222/\346\211\276\347\241\254\345\270\201-\345\212\250\346\200\201\350\247\204\345\210\222\347\211\210.js"
new file mode 100644
index 0000000..ce36dd1
--- /dev/null
+++ "b/\345\212\250\346\200\201\350\247\204\345\210\222/\346\211\276\347\241\254\345\270\201-\345\212\250\346\200\201\350\247\204\345\210\222\347\211\210.js"
@@ -0,0 +1,26 @@
+const coinChange = (coins, targetAmount) => {
+ // 初始化备忘录,用Infinity填满备忘录,Infinity说明该值不可以用硬币凑出来
+ const dp = new Array(targetAmount + 1).fill(Infinity);
+
+ // 设置初始条件为0 这一项无法用公式推导出来
+ dp[0] = 0;
+
+ for (let amount = 1; amount <= targetAmount; amount++) {
+ for (let j = 0; j < coins.length; j++) {
+ let coin = coins[j];
+ if (coin <= amount) {
+ // 根据动态转移方程 求出当前面值需要的硬币数最小值
+ dp[amount] = Math.min(
+ dp[amount],
+ // 比如目标15元 使用5元硬币 拆分为 dp(15 - 5) + 1
+ dp[amount - coin] + 1
+ );
+ }
+ }
+ }
+
+ // 如果 `dp[amount] === Infinity`说明没有最优解返回-1,否则返回最优解
+ return dp[targetAmount] === Infinity ? -1 : dp[targetAmount];
+};
+
+console.log(coinChange([1, 5, 11], 21))
diff --git "a/\345\212\250\346\200\201\350\247\204\345\210\222/\346\211\276\347\241\254\345\270\201-\350\256\260\345\277\206\351\200\222\345\275\222\347\211\210.js" "b/\345\212\250\346\200\201\350\247\204\345\210\222/\346\211\276\347\241\254\345\270\201-\350\256\260\345\277\206\351\200\222\345\275\222\347\211\210.js"
new file mode 100644
index 0000000..1affffd
--- /dev/null
+++ "b/\345\212\250\346\200\201\350\247\204\345\210\222/\346\211\276\347\241\254\345\270\201-\350\256\260\345\277\206\351\200\222\345\275\222\347\211\210.js"
@@ -0,0 +1,28 @@
+function f(n) {
+ function makeChange(amount) {
+ if (amount <= 0) return 0;
+
+ // 校验是否已经在备忘录中存在结果,如果存在返回即可
+ if (cache[amount]) return cache[amount];
+
+ let min = Infinity;
+ if (amount >= 1) {
+ min = Math.min(makeChange(amount - 1) + 1, min);
+ }
+
+ if (amount >= 5) {
+ min = Math.min(makeChange(amount - 5) + 1, min);
+ }
+
+ if (amount >= 11) {
+ min = Math.min(makeChange(amount - 11) + 1, min);
+ }
+
+ return (cache[amount] = min);
+ }
+ // 备忘录
+ const cache = [];
+ return makeChange(n);
+}
+
+console.log(f(5000));
diff --git "a/\345\212\250\346\200\201\350\247\204\345\210\222/\346\211\276\347\241\254\345\270\201-\351\200\222\345\275\222\347\211\210.js" "b/\345\212\250\346\200\201\350\247\204\345\210\222/\346\211\276\347\241\254\345\270\201-\351\200\222\345\275\222\347\211\210.js"
new file mode 100644
index 0000000..f79b8e8
--- /dev/null
+++ "b/\345\212\250\346\200\201\350\247\204\345\210\222/\346\211\276\347\241\254\345\270\201-\351\200\222\345\275\222\347\211\210.js"
@@ -0,0 +1,32 @@
+// https://juejin.im/post/5e86d0ad6fb9a03c387f3342
+
+/**
+ * 动态规划的前置思想,把问题拆分成子问题。
+ * 比如f(15),可以拆分成min(
+ * f(4) + 11 * 1,
+ * f(10) + 5 * 1,
+ * f(14) + 1 * 1
+ * )
+ * 然后这里的f(4)、f(10)、f(14) 进一步按照这个步骤值拆分。
+ * 这种做法的缺点是容易爆栈。
+ * @param {number} n
+ */
+function f(n) {
+ if (n === 0) return 0;
+ let min = Infinity;
+ if (n >= 1) {
+ min = Math.min(f(n - 1) + 1, min);
+ }
+
+ if (n >= 5) {
+ min = Math.min(f(n - 5) + 1, min);
+ }
+
+ if (n >= 11) {
+ min = Math.min(f(n - 11) + 1, min);
+ }
+
+ return min;
+}
+
+console.log(f(50)); // 3
diff --git "a/\345\212\250\346\200\201\350\247\204\345\210\222/\346\213\254\345\217\267\347\224\237\346\210\220-22.js" "b/\345\212\250\346\200\201\350\247\204\345\210\222/\346\213\254\345\217\267\347\224\237\346\210\220-22.js"
new file mode 100644
index 0000000..07735c1
--- /dev/null
+++ "b/\345\212\250\346\200\201\350\247\204\345\210\222/\346\213\254\345\217\267\347\224\237\346\210\220-22.js"
@@ -0,0 +1,23 @@
+let generateParenthesis = function (n) {
+ let dp = []
+ dp[0] = ['']
+ dp[1] = ['()']
+
+ for (let i = 2; i <= n; i++) {
+ let res = []
+ for (let j = 0; j <= i - 1; j++) {
+ let inners = dp[j]
+ let outers = dp[i - 1 - j]
+
+ for (let inner of inners) {
+ for (let outer of outers) {
+ res.push(`(${inner})${outer}`)
+ }
+ }
+ }
+ dp[i] = res
+ }
+ return dp[n]
+};
+
+console.log(generateParenthesis(4))
\ No newline at end of file
diff --git "a/\345\212\250\346\200\201\350\247\204\345\210\222/\346\226\220\346\263\242\351\202\243\345\245\221\346\225\260\345\210\227-509.js" "b/\345\212\250\346\200\201\350\247\204\345\210\222/\346\226\220\346\263\242\351\202\243\345\245\221\346\225\260\345\210\227-509.js"
new file mode 100644
index 0000000..c4f56f9
--- /dev/null
+++ "b/\345\212\250\346\200\201\350\247\204\345\210\222/\346\226\220\346\263\242\351\202\243\345\245\221\346\225\260\345\210\227-509.js"
@@ -0,0 +1,56 @@
+/**
+ * @param {number} N
+ * @return {number}
+ */
+let fib = function (N) {
+ let prev = 1n
+ let prevPrev = 1n
+
+ for (let i = 2; i <= N; i++) {
+ let current = prev + prevPrev
+ prevPrev = prev
+ prev = current
+ }
+
+ return prev
+};
+
+// let fib = function (N) {
+// let dp = []
+
+// dp[0] = 0n;
+// dp[1] = 1n;
+
+// for (let i = 2; i <= N; i++) {
+// dp[i] = dp[i - 1] + dp[i - 2];
+// }
+
+// return dp[N];
+// };
+
+// let fib = (function () {
+// let memo = new Map();
+// return function (n) {
+// // 优先从记忆里取 找到就直接 return
+// // 否则又要进入下面的递归逻辑 非常耗时
+// let memorized = memo.get(n);
+// if (memorized) {
+// return memorized;
+// }
+
+// if (n == 1 || n == 2) {
+// return 1;
+// }
+
+// let f1 = fib(n - 1)
+// let f2 = fib(n - 2)
+
+// // 记忆下来
+// memo.set(n - 1, f1)
+// memo.set(n - 2, f2)
+
+// return f1 + f2
+// };
+// })();
+
+console.log(fib(100000));
diff --git "a/\345\212\250\346\200\201\350\247\204\345\210\222/\346\227\240\351\207\215\345\217\240\345\214\272\351\227\264-435.js" "b/\345\212\250\346\200\201\350\247\204\345\210\222/\346\227\240\351\207\215\345\217\240\345\214\272\351\227\264-435.js"
new file mode 100644
index 0000000..c95bbf1
--- /dev/null
+++ "b/\345\212\250\346\200\201\350\247\204\345\210\222/\346\227\240\351\207\215\345\217\240\345\214\272\351\227\264-435.js"
@@ -0,0 +1,31 @@
+/**
+ * @param {number[][]} intervals
+ * @return {number}
+ */
+let eraseOverlapIntervals = function (intervals) {
+ let n = intervals.length
+ if (!n) {
+ return 0
+ }
+
+ // 按照起始点排序
+ intervals.sort((a, b) => a[0] - b[0])
+
+ // dp[i] 表示从 [0, i] 能构成的最长的无重叠区间的个数
+ let dp = []
+ dp[0] = 1
+
+ for (let i = 1; i < n; i++) {
+ let max = 1
+ let [curStart] = intervals[i]
+ for (let j = 0; j < i; j++) {
+ let [prevStart, prevEnd] = intervals[j]
+ if (prevEnd <= curStart) {
+ max = Math.max(max, dp[j] + 1)
+ }
+ }
+ dp[i] = max
+ }
+
+ return n - Math.max(...dp)
+};
\ No newline at end of file
diff --git "a/\345\212\250\346\200\201\350\247\204\345\210\222/\346\234\200\345\244\247\345\255\220\345\272\217\345\222\214-53.js" "b/\345\212\250\346\200\201\350\247\204\345\210\222/\346\234\200\345\244\247\345\255\220\345\272\217\345\222\214-53.js"
new file mode 100644
index 0000000..666e03a
--- /dev/null
+++ "b/\345\212\250\346\200\201\350\247\204\345\210\222/\346\234\200\345\244\247\345\255\220\345\272\217\345\222\214-53.js"
@@ -0,0 +1,18 @@
+/**
+ * @param {number[]} nums
+ * @return {number}
+ */
+let maxSubArray = function(nums) {
+ let n = nums.length;
+ let dp = [];
+
+ dp[n - 1] = nums[n - 1];
+
+ for (let i = n - 2; i >= 0; i--) {
+ let pickSelf = nums[i];
+ let pickWithNext = pickSelf + dp[i + 1];
+ dp[i] = Math.max(pickSelf, pickWithNext);
+ }
+
+ return Math.max(...dp);
+};
\ No newline at end of file
diff --git "a/\345\212\250\346\200\201\350\247\204\345\210\222/\346\234\200\345\244\247\346\255\243\346\226\271\345\275\242-221.js" "b/\345\212\250\346\200\201\350\247\204\345\210\222/\346\234\200\345\244\247\346\255\243\346\226\271\345\275\242-221.js"
new file mode 100644
index 0000000..26c4815
--- /dev/null
+++ "b/\345\212\250\346\200\201\350\247\204\345\210\222/\346\234\200\345\244\247\346\255\243\346\226\271\345\275\242-221.js"
@@ -0,0 +1,44 @@
+/**
+ * @param {character[][]} matrix
+ * @return {number}
+ */
+let maximalSquare = function (matrix) {
+ let maxY = matrix.length
+ if (!maxY) return 0
+ let maxX = matrix[0].length
+
+ let dp = []
+ let max = 0
+
+ let dpBasic = (y, x) => {
+ if (matrix[y][x] === "1") {
+ max = 1
+ dp[y][x] = 1
+ } else {
+ dp[y][x] = 0
+ }
+ }
+ for (let y = 0; y < maxY; y++) {
+ dp[y] = []
+ dpBasic(y, 0)
+ }
+ for (let x = 1; x < maxX; x++) {
+ dpBasic(0, x)
+ }
+
+ for (let y = 1; y < maxY; y++) {
+ for (let x = 1; x < maxX; x++) {
+ let val = matrix[y][x]
+ if (val === "0") {
+ dp[y][x] = 0
+ } else {
+ let left = dp[y][x - 1]
+ let top = dp[y - 1][x]
+ let leftTop = dp[y - 1][x - 1]
+ dp[y][x] = Math.min(left, top, leftTop) + 1
+ max = Math.max(max, dp[y][x])
+ }
+ }
+ }
+ return max * max
+}
diff --git "a/\345\212\250\346\200\201\350\247\204\345\210\222/\346\234\200\345\260\217\350\267\257\345\276\204\345\222\214-64.js" "b/\345\212\250\346\200\201\350\247\204\345\210\222/\346\234\200\345\260\217\350\267\257\345\276\204\345\222\214-64.js"
new file mode 100644
index 0000000..8380b9f
--- /dev/null
+++ "b/\345\212\250\346\200\201\350\247\204\345\210\222/\346\234\200\345\260\217\350\267\257\345\276\204\345\222\214-64.js"
@@ -0,0 +1,43 @@
+/**
+ * @param {number[][]} grid
+ * @return {number}
+ */
+let minPathSum = function (grid) {
+ let y = grid.length
+ if (!y) {
+ return 0
+ }
+ let x = grid[0].length
+
+ let dp = []
+ for (let i = 0; i < y; i++) {
+ dp[i] = []
+ }
+
+ dp[0][0] = grid[0][0]
+
+ // 第一行的基础状态 记得加上左边格子的值
+ for (let j = 1; j < x; j++) {
+ dp[0][j] = grid[0][j] + dp[0][j - 1]
+ }
+
+ // 第一列的基础状态 加上上方格子的最优解即可
+ for (let i = 1; i < y; i++) {
+ dp[i][0] = grid[i][0] + dp[i - 1][0]
+ }
+
+ // 开始求左上往右下求解
+ for (let i = 1; i < grid.length; i++) {
+ for (let j = 1; j < grid[i].length; j++) {
+ let cur = grid[i][j]
+ let fromUp = cur + (dp[i - 1][j] !== undefined ? dp[i - 1][j]: Infinity)
+ let fromLeft = cur + (dp[i][j - 1] !== undefined ? dp[i][j - 1]: Infinity)
+
+ dp[i][j] = Math.min(
+ fromUp,
+ fromLeft
+ )
+ }
+ }
+ return dp[y - 1][x - 1]
+};
\ No newline at end of file
diff --git "a/\345\212\250\346\200\201\350\247\204\345\210\222/\346\234\200\351\225\277\344\270\212\345\215\207\345\255\220\345\272\217\345\210\227-300.js" "b/\345\212\250\346\200\201\350\247\204\345\210\222/\346\234\200\351\225\277\344\270\212\345\215\207\345\255\220\345\272\217\345\210\227-300.js"
new file mode 100644
index 0000000..622c453
--- /dev/null
+++ "b/\345\212\250\346\200\201\350\247\204\345\210\222/\346\234\200\351\225\277\344\270\212\345\215\207\345\255\220\345\272\217\345\210\227-300.js"
@@ -0,0 +1,28 @@
+/**
+ * @param {number[]} nums
+ * @return {number}
+ */
+let lengthOfLIS = function (nums) {
+ let dp = []
+ let n = nums.length
+ if (!n) {
+ return 0
+ }
+
+ dp[0] = 1
+ for (let i = 1; i < n; i++) {
+ let num = nums[i]
+ let max = 1
+ // j 从 [0, i) 依次求出可以和 i 组成的最长上升子序列
+ for (let j = 0; j < i; j++) {
+ let prevNum = nums[j]
+ if (num > prevNum) {
+ // 循环中不断更新 max 值
+ max = Math.max(max, dp[j] + 1)
+ }
+ }
+ dp[i] = max
+ }
+
+ return Math.max(...dp)
+}
diff --git "a/\345\212\250\346\200\201\350\247\204\345\210\222/\346\234\200\351\225\277\345\205\254\345\205\261\345\255\220\345\272\217\345\210\227-1143.js" "b/\345\212\250\346\200\201\350\247\204\345\210\222/\346\234\200\351\225\277\345\205\254\345\205\261\345\255\220\345\272\217\345\210\227-1143.js"
new file mode 100644
index 0000000..71c8e51
--- /dev/null
+++ "b/\345\212\250\346\200\201\350\247\204\345\210\222/\346\234\200\351\225\277\345\205\254\345\205\261\345\255\220\345\272\217\345\210\227-1143.js"
@@ -0,0 +1,32 @@
+/**
+ * @param {string} text1
+ * @param {string} text2
+ * @return {number}
+ */
+let longestCommonSubsequence = function (text1, text2) {
+ let n1 = text1.length
+ let n2 = text2.length
+
+ let dp = []
+
+ for (let i1 = 0; i1 <= n1; i1++) {
+ dp[i1] = []
+ dp[i1][0] = 0
+ }
+ dp[0] = Array(n2 + 1).fill(0)
+
+ for (let i1 = 1; i1 <= n1; i1++) {
+ for (let i2 = 1; i2 <= n2; i2++) {
+ let str1 = text1[i1 - 1]
+ let str2 = text2[i2 - 1]
+
+ if (str1 === str2) {
+ dp[i1][i2] = 1 + dp[i1 - 1][i2 - 1]
+ }else {
+ dp[i1][i2] = Math.max(dp[i1 - 1][i2], dp[i1][i2 - 1])
+ }
+ }
+ }
+
+ return dp[n1][n2]
+};
\ No newline at end of file
diff --git "a/\345\212\250\346\200\201\350\247\204\345\210\222/\346\234\200\351\225\277\345\215\225\350\257\215-\351\235\242\350\257\225\351\242\230 17.15.js" "b/\345\212\250\346\200\201\350\247\204\345\210\222/\346\234\200\351\225\277\345\215\225\350\257\215-\351\235\242\350\257\225\351\242\230 17.15.js"
new file mode 100644
index 0000000..fe82f42
--- /dev/null
+++ "b/\345\212\250\346\200\201\350\247\204\345\210\222/\346\234\200\351\225\277\345\215\225\350\257\215-\351\235\242\350\257\225\351\242\230 17.15.js"
@@ -0,0 +1,49 @@
+/**
+ * @param {string} s
+ * @param {string[]} wordDict
+ * @return {boolean}
+ */
+let wordBreak = function (s, wordDict) {
+ let n = s.length
+ if (!n) return true
+
+ let wordSet = new Set(wordDict)
+ let dp = []
+ dp[0] = true
+
+ for (let i = 0; i <= n; i++) {
+ for (let j = i; j >= 0; j--) {
+ let word = s.slice(j, i)
+ if (wordSet.has(word) && dp[j]) {
+ dp[i] = true
+ break
+ }
+ }
+ }
+
+ return !!dp[n]
+}
+/**
+ * @param {string[]} words
+ * @return {string}
+ */
+let longestWord = function (words) {
+ // 先长度降序 后字典序升序 排序
+ words.sort((a, b) => {
+ let diff = b.length - a.length
+ if (diff !== 0) {
+ return diff
+ } else {
+ return a < b ? -1 : 1
+ }
+ })
+ words = Array.from(new Set(words))
+ for (let i = 0; i < words.length; i++) {
+ let word = words[i]
+ let rest = words.slice(0, i).concat(words.slice(i + 1))
+ if (wordBreak(word, rest)) {
+ return word
+ }
+ }
+ return ""
+}
\ No newline at end of file
diff --git "a/\345\212\250\346\200\201\350\247\204\345\210\222/\346\234\200\351\225\277\345\233\236\346\226\207\345\255\220\344\270\262-5.js" "b/\345\212\250\346\200\201\350\247\204\345\210\222/\346\234\200\351\225\277\345\233\236\346\226\207\345\255\220\344\270\262-5.js"
new file mode 100644
index 0000000..9876ba0
--- /dev/null
+++ "b/\345\212\250\346\200\201\350\247\204\345\210\222/\346\234\200\351\225\277\345\233\236\346\226\207\345\255\220\344\270\262-5.js"
@@ -0,0 +1,77 @@
+/**
+ * 动态规划
+ * @param {string} s
+ * @return {string}
+ */
+// let longestPalindrome = function (s) {
+// let n = s.length
+// if (n < 2) {
+// return s
+// }
+
+// let dp = []
+// for (let i = 0; i < n; i++) {
+// dp[i] = []
+// dp[i][i] = true
+// }
+
+// let max = 0
+// let begin = 0
+// for (let j = 1; j < n; j++) {
+// for (let i = 0; i < j; i++) {
+// if (s[j] !== s[i]) {
+// dp[i][j] = false
+// } else {
+// let indent = dp[i + 1][j - 1]
+// if (indent === undefined || indent === true) {
+// dp[i][j] = true
+// }else {
+// dp[i][j] = false
+// }
+// }
+
+// if (dp[i][j] === true && j - i > max) {
+// max = j - i
+// begin = i
+// }
+// }
+// }
+// console.log('dp', dp)
+// return s.substr(begin, max + 1)
+// }
+
+/**
+ * 中心扩散法
+ * @param {string} s
+ * @return {string}
+ */
+let longestPalindrome = function (s) {
+ let n = s.length
+ if (n < 2) {
+ return s
+ }
+
+ let begin = 0
+ let max = 1
+
+ let spread = (start, end) => {
+ while (s[start] === s[end] && start >= 0 && end < n) {
+ let len = end - start + 1
+ if (len > max) {
+ max = len
+ begin = start
+ }
+ start--
+ end++
+ }
+ }
+
+ for (let mid = 0; mid < n; mid++) {
+ spread(mid, mid)
+ spread(mid, mid + 1)
+ }
+
+ return s.substr(begin, max)
+}
+
+console.log(longestPalindrome("babad"))
diff --git "a/\345\212\250\346\200\201\350\247\204\345\210\222/\346\234\200\351\225\277\351\207\215\345\244\215\345\255\220\346\225\260\347\273\204-718.js" "b/\345\212\250\346\200\201\350\247\204\345\210\222/\346\234\200\351\225\277\351\207\215\345\244\215\345\255\220\346\225\260\347\273\204-718.js"
new file mode 100644
index 0000000..a4dfc61
--- /dev/null
+++ "b/\345\212\250\346\200\201\350\247\204\345\210\222/\346\234\200\351\225\277\351\207\215\345\244\215\345\255\220\346\225\260\347\273\204-718.js"
@@ -0,0 +1,33 @@
+/**
+ * @param {number[]} A
+ * @param {number[]} B
+ * @return {number}
+ */
+let findLength = function (A, B) {
+ let dp = []
+ let al = A.length
+ let bl = B.length
+
+ for (let i = 0; i <= al; i++) {
+ dp[i] = []
+ for (let j = 0; j <= bl; j++) {
+ dp[i][j] = 0
+ }
+ }
+
+ let max = 0
+ for (let i = al - 1; i >= 0; i--) {
+ for (let j = bl - 1; j >= 0; j--) {
+ let a = A[i]
+ let b = B[j]
+
+ if (a === b) {
+ dp[i][j] = dp[i + 1][j + 1] + 1
+ max = Math.max(max, dp[i][j])
+ } else {
+ dp[i][j] = 0
+ }
+ }
+ }
+ return max
+}
diff --git "a/\345\212\250\346\200\201\350\247\204\345\210\222/\347\210\254\346\245\274\346\242\257-70.js" "b/\345\212\250\346\200\201\350\247\204\345\210\222/\347\210\254\346\245\274\346\242\257-70.js"
new file mode 100644
index 0000000..05e1665
--- /dev/null
+++ "b/\345\212\250\346\200\201\350\247\204\345\210\222/\347\210\254\346\245\274\346\242\257-70.js"
@@ -0,0 +1,42 @@
+/**
+ * 假设你正在爬楼梯。需要 n 阶你才能到达楼顶。
+
+ 每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?
+
+ 注意:给定 n 是一个正整数。
+
+ 示例 1:
+
+ 输入: 2
+ 输出: 2
+ 解释: 有两种方法可以爬到楼顶。
+ 1. 1 阶 + 1 阶
+ 2. 2 阶
+
+
+ 来源:力扣(LeetCode)
+ 链接:https://leetcode-cn.com/problems/climbing-stairs
+ 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
+ */
+
+/**
+ * 爬n阶楼梯,可以拆分为
+ * 爬1阶加爬f(n-1)阶 + 爬2阶加爬f(n-2)阶 的方式。
+ * @param {number} n
+ * @return {number}
+ */
+let climbStairs = function (n) {
+ let dp = new Array(n + 1).fill(0);
+
+ // 初始条件 爬一阶只有一种方式
+ dp[1] = 1;
+ dp[2] = 2
+
+ for (let i = 3; i <= n; i++) {
+ dp[i] = dp[i - 1] + dp[i - 2];
+ }
+
+ return dp[n];
+};
+
+console.log(climbStairs(3))
diff --git "a/\345\212\250\346\200\201\350\247\204\345\210\222/\347\233\256\346\240\207\345\222\214-494.js" "b/\345\212\250\346\200\201\350\247\204\345\210\222/\347\233\256\346\240\207\345\222\214-494.js"
new file mode 100644
index 0000000..d0b0687
--- /dev/null
+++ "b/\345\212\250\346\200\201\350\247\204\345\210\222/\347\233\256\346\240\207\345\222\214-494.js"
@@ -0,0 +1,39 @@
+/**
+ * @param {number[]} nums
+ * @param {number} S
+ * @return {number}
+ */
+let findTargetSumWays = function (nums, S) {
+ let ns = nums.length
+ if (!ns) {
+ return 0
+ }
+ let min = nums.reduce((sum, cur) => sum - cur, 0)
+ let max = nums.reduce((sum, cur) => sum + cur, 0)
+
+ let dp = []
+ for (let n = 0; n < ns; n++) {
+ dp[n] = []
+ }
+
+ // 基础状态
+ for (let s = min; s <= max; s++) {
+ let num = nums[0]
+ let pickPositive = s === num ? 1 : 0
+ // 选负数形态
+ let pickNegative = -s === num ? 1 : 0
+ dp[0][s] = pickPositive + pickNegative
+ }
+
+ for (let n = 1; n < ns; n++) {
+ for (let s = min; s <= max; s++) {
+ let num = nums[n]
+ // 选正数形态
+ let pickPositive = dp[n - 1][s - num] || 0
+ // 选负数形态
+ let pickNegative = dp[n - 1][s + num] || 0
+ dp[n][s] = pickNegative + pickPositive
+ }
+ }
+ return dp[ns - 1][S] || 0
+}
diff --git "a/\345\212\250\346\200\201\350\247\204\345\210\222/\351\233\266\351\222\261\345\205\221\346\215\242II-518.js" "b/\345\212\250\346\200\201\350\247\204\345\210\222/\351\233\266\351\222\261\345\205\221\346\215\242II-518.js"
new file mode 100644
index 0000000..d2fcc5e
--- /dev/null
+++ "b/\345\212\250\346\200\201\350\247\204\345\210\222/\351\233\266\351\222\261\345\205\221\346\215\242II-518.js"
@@ -0,0 +1,22 @@
+/**
+ * @param {number} amount
+ * @param {number[]} coins
+ * @return {number}
+ */
+let change = function (amount, coins) {
+ let dp = new Array(amount + 1).fill(0);
+
+ dp[0] = 1;
+
+ for (let coin of coins) {
+ for (let i = 1; i <= amount; i++) {
+ if (i >= coin) {
+ dp[i] += dp[i - coin];
+ }
+ }
+ }
+
+ return dp[amount];
+};
+
+console.log(change(5, [1, 2, 5]));
diff --git "a/\345\212\250\346\200\201\350\247\204\345\210\222/\351\235\242\350\257\225\351\242\23008.11.\347\241\254\345\270\201.js" "b/\345\212\250\346\200\201\350\247\204\345\210\222/\351\235\242\350\257\225\351\242\23008.11.\347\241\254\345\270\201.js"
new file mode 100644
index 0000000..6b29456
--- /dev/null
+++ "b/\345\212\250\346\200\201\350\247\204\345\210\222/\351\235\242\350\257\225\351\242\23008.11.\347\241\254\345\270\201.js"
@@ -0,0 +1,45 @@
+let coins = [1, 5, 10, 25];
+let waysToChange = function (n) {
+ let cl = coins.length;
+ if (n === 0) return 0;
+
+ let dp = new Array(cl);
+ for (let i = 0; i < cl; i++) {
+ dp[i] = new Array(n + 1);
+ }
+
+ for (let i = 0; i < cl; i++) {
+ dp[i][0] = 1
+ }
+
+ for (let i = 0; i < dp.length; i++) {
+ for (let j = 1; j <= n; j++) {
+ let coin = coins[i];
+ let dpPrev = dp[i - 1];
+ // 考虑不用当前硬币
+ let pickPrev = dpPrev ? dpPrev[j] : 0;
+
+ // 考虑加上当前硬币
+ let pickCurrentAndPrev = 0;
+ if (j >= coin) {
+ // 用了当前的硬币以后 剩余的面值
+ let rest = j - coin;
+ let pickRest = dp[i][rest];
+ if (pickRest > 0) {
+ // 这个方式数其实就是凑剩余硬币的方式数
+ // 比如 以硬币5和面值10来说
+ // 拿出了5 发现剩余面值是5
+ // 凑剩余面值5的情况是 5 + 11111
+ // 所以拿出5来凑的方式是1种
+ pickCurrentAndPrev = pickRest;
+ }
+ }
+
+ dp[i][j] = (pickPrev + pickCurrentAndPrev) % 1000000007;
+ }
+ }
+
+ return dp[cl - 1][n];
+};
+
+console.log(waysToChange(61)); // 73
diff --git "a/\347\256\227\346\263\225/\345\215\225\345\200\274\344\272\214\345\217\211\346\240\221.js" "b/\345\215\225\345\200\274\344\272\214\345\217\211\346\240\221.js"
similarity index 73%
rename from "\347\256\227\346\263\225/\345\215\225\345\200\274\344\272\214\345\217\211\346\240\221.js"
rename to "\345\215\225\345\200\274\344\272\214\345\217\211\346\240\221.js"
index da50d4a..1c862a2 100644
--- "a/\347\256\227\346\263\225/\345\215\225\345\200\274\344\272\214\345\217\211\346\240\221.js"
+++ "b/\345\215\225\345\200\274\344\272\214\345\217\211\346\240\221.js"
@@ -2,10 +2,10 @@
* @param {TreeNode} root
* @return {boolean}
*/
-var isUnivalTree = function(root) {
- var values = []
+let isUnivalTree = function(root) {
+ let values = []
dfs(root, values)
- var first = values[0]
+ let first = values[0]
return values.every(val => val === first)
};
@@ -18,9 +18,9 @@ function dfs(node, values) {
-var TreeNode = require('./二叉树.js')
+let TreeNode = require('./工具/二叉树.js')
-var treeNode = new TreeNode(1)
+let treeNode = new TreeNode(1)
treeNode.left = new TreeNode(1)
treeNode.right = new TreeNode(1)
diff --git "a/\345\217\214\346\214\207\351\222\210/\345\210\240\351\231\244\346\216\222\345\272\217\346\225\260\347\273\204\344\270\255\347\232\204\351\207\215\345\244\215\351\241\271-26.js" "b/\345\217\214\346\214\207\351\222\210/\345\210\240\351\231\244\346\216\222\345\272\217\346\225\260\347\273\204\344\270\255\347\232\204\351\207\215\345\244\215\351\241\271-26.js"
new file mode 100644
index 0000000..94e13aa
--- /dev/null
+++ "b/\345\217\214\346\214\207\351\222\210/\345\210\240\351\231\244\346\216\222\345\272\217\346\225\260\347\273\204\344\270\255\347\232\204\351\207\215\345\244\215\351\241\271-26.js"
@@ -0,0 +1,29 @@
+/**
+ * @param {number[]} nums
+ * @return {number}
+ */
+let removeDuplicates = function (nums) {
+ // 快指针
+ let i = 0;
+ // 慢指针
+ let j = 0;
+
+ while (i < nums.length) {
+ let fast = nums[i];
+ let slot = nums[j];
+
+ // 快慢不相等,说明找到了一个新的值
+ // 把慢指针的位置更新,并且赋值成新的值,继续等待下一个新值。
+ if (fast !== slot) {
+ j++;
+ nums[j] = fast;
+ }
+ i++;
+ }
+
+ console.log(nums);
+
+ return j + 1;
+};
+
+console.log(removeDuplicates([0, 0, 1, 1, 1, 2, 2, 3, 3, 4]));
diff --git "a/\345\217\214\346\214\207\351\222\210/\345\220\210\345\271\266\344\270\244\344\270\252\346\234\211\345\272\217\346\225\260\347\273\204-88.js" "b/\345\217\214\346\214\207\351\222\210/\345\220\210\345\271\266\344\270\244\344\270\252\346\234\211\345\272\217\346\225\260\347\273\204-88.js"
new file mode 100644
index 0000000..2117c9e
--- /dev/null
+++ "b/\345\217\214\346\214\207\351\222\210/\345\220\210\345\271\266\344\270\244\344\270\252\346\234\211\345\272\217\346\225\260\347\273\204-88.js"
@@ -0,0 +1,42 @@
+/*
+ * @lc app=leetcode.cn id=88 lang=javascript
+ *
+ * [88] 合并两个有序数组
+ */
+
+// @lc code=start
+/**
+ * @param {number[]} nums1
+ * @param {number} m
+ * @param {number[]} nums2
+ * @param {number} n
+ * @return {void} Do not return anything, modify nums1 in-place instead.
+ */
+let merge = function (arr1, m, arr2, n) {
+ // 两个指针指向数组非空位置的末尾
+ let i = m - 1;
+ let j = n - 1;
+ // 第三个指针指向第一个数组的末尾 填充数据
+ let k = arr1.length - 1;
+
+ while (i >= 0 && j >= 0) {
+ let num1 = arr1[i];
+ let num2 = arr2[j];
+
+ if (num1 > num2) {
+ arr1[k] = num1;
+ i--;
+ } else {
+ arr1[k] = num2;
+ j--;
+ }
+ k--;
+ }
+
+ while (j >= 0) {
+ arr1[k] = arr2[j];
+ j--;
+ k--;
+ }
+};
+// @lc code=end
diff --git "a/\345\217\214\346\214\207\351\222\210/\346\220\234\347\264\242\344\272\214\347\273\264\347\237\251\351\230\265 II-240.js" "b/\345\217\214\346\214\207\351\222\210/\346\220\234\347\264\242\344\272\214\347\273\264\347\237\251\351\230\265 II-240.js"
new file mode 100644
index 0000000..54f7a34
--- /dev/null
+++ "b/\345\217\214\346\214\207\351\222\210/\346\220\234\347\264\242\344\272\214\347\273\264\347\237\251\351\230\265 II-240.js"
@@ -0,0 +1,24 @@
+/**
+ * @param {number[][]} matrix
+ * @param {number} target
+ * @return {boolean}
+ */
+let searchMatrix = function (matrix, target) {
+ let y = matrix.length
+ if (!y) return false
+ let x = matrix[0].length
+
+ let row = y - 1
+ let column = 0
+ while (row >= 0 && column < x) {
+ let val = matrix[row][column]
+ if (val > target) {
+ row--
+ } else if (val < target) {
+ column++
+ } else if (val === target) {
+ return true
+ }
+ }
+ return false
+};
\ No newline at end of file
diff --git "a/\345\217\214\346\214\207\351\222\210/\346\234\200\346\216\245\350\277\221\347\232\204\344\270\211\346\225\260\344\271\213\345\222\214-16.js" "b/\345\217\214\346\214\207\351\222\210/\346\234\200\346\216\245\350\277\221\347\232\204\344\270\211\346\225\260\344\271\213\345\222\214-16.js"
new file mode 100644
index 0000000..70d7631
--- /dev/null
+++ "b/\345\217\214\346\214\207\351\222\210/\346\234\200\346\216\245\350\277\221\347\232\204\344\270\211\346\225\260\344\271\213\345\222\214-16.js"
@@ -0,0 +1,49 @@
+/**
+ * @param {number[]} nums
+ * @param {number} target
+ * @return {number}
+ */
+let threeSumClosest = function (nums, target) {
+ let n = nums.length
+ if (n === 3) {
+ return getSum(nums)
+ }
+ // 先升序排序 此为解题的前置条件
+ nums.sort((a, b) => a - b)
+
+ let min = Infinity // 和 target 的最小差
+ let res
+
+ // 从左往右依次尝试定一个基础指针 右边至少再保留两位 否则无法凑成3个
+ for (let i = 0; i <= nums.length - 3; i++) {
+ let basic = nums[i]
+ let left = i + 1 // 左指针先从 i 右侧的第一位开始尝试
+ let right = n - 1 // 右指针先从数组最后一项开始尝试
+
+ while (left < right) {
+ let sum = basic + nums[left] + nums[right] // 三数求和
+ // 更新最小差
+ let diff = Math.abs(sum - target)
+ if (diff < min) {
+ min = diff
+ res = sum
+ }
+ if (sum < target) {
+ // 求出的和如果小于目标值的话 可以尝试把左指针右移 扩大值
+ left++
+ } else if (sum > target) {
+ // 反之则右指针左移
+ right--
+ } else {
+ // 相等的话 差就为0 一定是答案
+ return sum
+ }
+ }
+ }
+
+ return res
+}
+
+function getSum(nums) {
+ return nums.reduce((total, cur) => total + cur, 0)
+}
diff --git "a/\345\217\214\346\214\207\351\222\210/\351\200\232\350\277\207\345\210\240\351\231\244\345\255\227\346\257\215\345\214\271\351\205\215\345\210\260\345\255\227\345\205\270\351\207\214\346\234\200\351\225\277\345\215\225\350\257\215-524.js" "b/\345\217\214\346\214\207\351\222\210/\351\200\232\350\277\207\345\210\240\351\231\244\345\255\227\346\257\215\345\214\271\351\205\215\345\210\260\345\255\227\345\205\270\351\207\214\346\234\200\351\225\277\345\215\225\350\257\215-524.js"
new file mode 100644
index 0000000..1da6eb0
--- /dev/null
+++ "b/\345\217\214\346\214\207\351\222\210/\351\200\232\350\277\207\345\210\240\351\231\244\345\255\227\346\257\215\345\214\271\351\205\215\345\210\260\345\255\227\345\205\270\351\207\214\346\234\200\351\225\277\345\215\225\350\257\215-524.js"
@@ -0,0 +1,30 @@
+/**
+ * @param {string} s
+ * @param {string[]} d
+ * @return {string}
+ */
+let findLongestWord = function (s, d) {
+ let n = d.length
+ let points = Array(n).fill(-1)
+
+ let find = ""
+ for (let i = 0; i < s.length; i++) {
+ let char = s[i]
+ for (let j = 0; j < n; j++) {
+ let targetChar = d[j][points[j] + 1]
+ if (char === targetChar) {
+ points[j]++
+ let word = d[j]
+ let wl = d[j].length
+ if (points[j] === wl - 1) {
+ let fl = find.length
+ if (wl > fl || (wl === fl && word < find)) {
+ find = word
+ }
+ }
+ }
+ }
+ }
+
+ return find
+}
\ No newline at end of file
diff --git "a/\345\217\257\350\242\253K\346\225\264\351\231\244\347\232\204\345\255\220\346\225\260\347\273\204.js" "b/\345\217\257\350\242\253K\346\225\264\351\231\244\347\232\204\345\255\220\346\225\260\347\273\204.js"
new file mode 100644
index 0000000..8349671
--- /dev/null
+++ "b/\345\217\257\350\242\253K\346\225\264\351\231\244\347\232\204\345\255\220\346\225\260\347\273\204.js"
@@ -0,0 +1,32 @@
+/**
+ * 暴力解 超时了
+ * @param {number[]} A
+ * @param {number} K
+ * @return {number}
+ */
+var subarraysDivByK = function (A, K) {
+ let prevPrefix = []
+ let currentPrefix = []
+ let count = 0
+ for (let i = A.length - 1; i >= 0; i--) {
+ let num = A[i]
+ judge(num)
+ for (let prev of prevPrefix) {
+ let sum = prev + num
+ judge(sum)
+ }
+ prevPrefix = currentPrefix
+ currentPrefix = []
+ }
+
+ function judge(num) {
+ if (num % K === 0 || num === 0) {
+ count++
+ }
+ currentPrefix.push(num)
+ }
+
+ return count
+}
+
+console.log(subarraysDivByK([4, 5, 0, -2, -3, 1], 5))
diff --git "a/\347\256\227\346\263\225/\345\220\210\345\271\266\344\270\244\344\270\252\346\234\211\345\272\217\346\225\260\347\273\204.js" "b/\345\220\210\345\271\266\344\270\244\344\270\252\346\234\211\345\272\217\346\225\260\347\273\204.js"
similarity index 97%
rename from "\347\256\227\346\263\225/\345\220\210\345\271\266\344\270\244\344\270\252\346\234\211\345\272\217\346\225\260\347\273\204.js"
rename to "\345\220\210\345\271\266\344\270\244\344\270\252\346\234\211\345\272\217\346\225\260\347\273\204.js"
index 404be99..7ee6b94 100644
--- "a/\347\256\227\346\263\225/\345\220\210\345\271\266\344\270\244\344\270\252\346\234\211\345\272\217\346\225\260\347\273\204.js"
+++ "b/\345\220\210\345\271\266\344\270\244\344\270\252\346\234\211\345\272\217\346\225\260\347\273\204.js"
@@ -47,7 +47,7 @@ const merge = function(nums1, m, nums2, n) {
}
}
-var a = [1, 2, 10, 0, 0, 0]
+let a = [1, 2, 10, 0, 0, 0]
merge(a, 3, [2, 5, 6, 7], 4)
console.log(a)
@@ -116,7 +116,7 @@ const merge2 = function(nums1, m, nums2, n) {
}
};
-var a2= [1, 2, 0, 0, 0, 0]
+let a2= [1, 2, 0, 0, 0, 0]
merge(a2, 2, [2, 5, 6], 4)
console.log(a2)
\ No newline at end of file
diff --git "a/\347\256\227\346\263\225/\345\220\210\345\271\266\344\270\244\344\270\252\346\234\211\345\272\217\351\223\276\350\241\250.js" "b/\345\220\210\345\271\266\344\270\244\344\270\252\346\234\211\345\272\217\351\223\276\350\241\250.js"
similarity index 84%
rename from "\347\256\227\346\263\225/\345\220\210\345\271\266\344\270\244\344\270\252\346\234\211\345\272\217\351\223\276\350\241\250.js"
rename to "\345\220\210\345\271\266\344\270\244\344\270\252\346\234\211\345\272\217\351\223\276\350\241\250.js"
index f6f7020..153df9a 100644
--- "a/\347\256\227\346\263\225/\345\220\210\345\271\266\344\270\244\344\270\252\346\234\211\345\272\217\351\223\276\350\241\250.js"
+++ "b/\345\220\210\345\271\266\344\270\244\344\270\252\346\234\211\345\272\217\351\223\276\350\241\250.js"
@@ -3,11 +3,11 @@ function ListNode(val) {
this.next = null
}
-var node1 = new ListNode(1)
+let node1 = new ListNode(1)
node1.next = new ListNode(2)
node1.next.next = new ListNode(4)
-var node2 = new ListNode(1)
+let node2 = new ListNode(1)
node2.next = new ListNode(3)
node2.next.next = new ListNode(4)
/**
@@ -15,17 +15,17 @@ node2.next.next = new ListNode(4)
* @param {ListNode} l2
* @return {ListNode}
*/
-var mergeTwoLists = function(l1, l2) {
- var arr = []
+let mergeTwoLists = function(l1, l2) {
+ let arr = []
if (!l1 && !l2) {
return null
}
while (l1 || l2) {
- var runL1 = () => {
+ let runL1 = () => {
arr.push(l1.val)
l1 = l1.next
}
- var runL2 = () => {
+ let runL2 = () => {
arr.push(l2.val)
l2 = l2.next
}
diff --git "a/\345\233\236\346\226\207\345\255\220\344\270\262-647.js" "b/\345\233\236\346\226\207\345\255\220\344\270\262-647.js"
new file mode 100644
index 0000000..3a9c237
--- /dev/null
+++ "b/\345\233\236\346\226\207\345\255\220\344\270\262-647.js"
@@ -0,0 +1,29 @@
+/**
+ * @param {string} s
+ * @return {number}
+ */
+let countSubstrings = function (s) {
+ let n = s.length
+ if (n < 2) {
+ return n
+ }
+
+ let count = 0
+
+ let spread = (start, end) => {
+ while (s[start] === s[end] && start >= 0 && end < n) {
+ start--
+ end++
+ count++
+ }
+ }
+
+ for (let mid = 0; mid < n; mid++) {
+ spread(mid, mid)
+ spread(mid, mid + 1)
+ }
+
+ return count
+}
+
+console.log(countSubstrings("a"))
diff --git "a/\347\256\227\346\263\225/\345\255\227\347\254\246\344\270\262\345\255\227\347\254\246\346\234\200\347\237\255\350\267\257\345\276\204.js" "b/\345\255\227\347\254\246\344\270\262\345\255\227\347\254\246\346\234\200\347\237\255\350\267\257\345\276\204.js"
similarity index 79%
rename from "\347\256\227\346\263\225/\345\255\227\347\254\246\344\270\262\345\255\227\347\254\246\346\234\200\347\237\255\350\267\257\345\276\204.js"
rename to "\345\255\227\347\254\246\344\270\262\345\255\227\347\254\246\346\234\200\347\237\255\350\267\257\345\276\204.js"
index 6692cc0..9014e11 100644
--- "a/\347\256\227\346\263\225/\345\255\227\347\254\246\344\270\262\345\255\227\347\254\246\346\234\200\347\237\255\350\267\257\345\276\204.js"
+++ "b/\345\255\227\347\254\246\344\270\262\345\255\227\347\254\246\346\234\200\347\237\255\350\267\257\345\276\204.js"
@@ -17,8 +17,8 @@ S 和 C 中的所有字母均为小写字母。
* @param {character} C
* @return {number[]}
*/
-var shortestToChar = function(S, C) {
- var sl = S.length
+let shortestToChar = function(S, C) {
+ let sl = S.length
if (sl === 0) {
return []
@@ -26,26 +26,26 @@ var shortestToChar = function(S, C) {
if (sl.length > 10000) {
S = S.substr(0, 10000)
}
- var pos = []
- var res = []
+ let pos = []
+ let res = []
// 先走一次循环 存储每个C值的位置 便于比对
- for (var i = 0; i < sl; i++) {
+ for (let i = 0; i < sl; i++) {
if (S[i] === C) {
pos.push(i)
}
}
- for (var i = 0; i < sl; i++) {
+ for (let i = 0; i < sl; i++) {
// 如果这个字符就是C 距离就是0
- var char = S[i]
+ let char = S[i]
if (char === C) {
res.push(0)
} else {
// 定一个最短距离变量
- var shortest = sl
+ let shortest = sl
// 循环C位置的数组 找出距离最短的 注意绝对值
- for (var j = 0; j < pos.length; j++) {
- var diff = pos[j] - i
+ for (let j = 0; j < pos.length; j++) {
+ let diff = pos[j] - i
diff = diff > 0 ? diff : Math.abs(diff)
if (diff < shortest) {
shortest = diff
diff --git "a/\345\267\245\345\205\267/\344\272\214\345\217\211\346\240\221.js" "b/\345\267\245\345\205\267/\344\272\214\345\217\211\346\240\221.js"
new file mode 100644
index 0000000..6664215
--- /dev/null
+++ "b/\345\267\245\345\205\267/\344\272\214\345\217\211\346\240\221.js"
@@ -0,0 +1,9 @@
+class TreeNode {
+ constructor(val) {
+ this.val = val
+ this.left = null
+ this.right = null
+ }
+}
+
+module.exports = TreeNode
\ No newline at end of file
diff --git "a/\345\267\245\345\205\267/\344\272\244\346\215\242.js" "b/\345\267\245\345\205\267/\344\272\244\346\215\242.js"
new file mode 100644
index 0000000..62e4e9a
--- /dev/null
+++ "b/\345\267\245\345\205\267/\344\272\244\346\215\242.js"
@@ -0,0 +1,7 @@
+function swap(arr, i, j) {
+ let temp = arr[i];
+ arr[i] = arr[j];
+ arr[j] = temp;
+};
+
+module.exports = swap
\ No newline at end of file
diff --git "a/\345\267\245\345\205\267/\346\216\222\345\272\217\351\200\237\345\272\246.js" "b/\345\267\245\345\205\267/\346\216\222\345\272\217\351\200\237\345\272\246.js"
new file mode 100644
index 0000000..9fc27af
--- /dev/null
+++ "b/\345\267\245\345\205\267/\346\216\222\345\272\217\351\200\237\345\272\246.js"
@@ -0,0 +1,91 @@
+const glob = require("glob")
+const path = require("path")
+const swap = require("./交换")
+const random = require("./随机值")
+
+function sortTest(sortFns, source, desc) {
+ console.log(desc)
+ const table = {}
+
+ if (typeof source === "function") {
+ source = source()
+ }
+
+ sortFns.forEach((fn) => {
+ const copy = source.slice()
+ const start = new Date().getTime()
+
+ try {
+ fn(copy)
+ } catch (e) {
+ return (table[fn.sortName] = {
+ 结果: "程序异常",
+ 原因: e.message,
+ })
+ }
+
+ const end = new Date().getTime()
+ const time = end - start
+ const timeStr = `${time}ms`
+ const success = isSorted(copy, source)
+
+ table[fn.sortName] = {
+ 耗时: timeStr,
+ 数据长度: source.length,
+ 结果: success ? "成功" : "失败",
+ }
+ })
+
+ console.table(table)
+}
+
+function getRandomArray(count) {
+ const arr = []
+ for (let i = 0; i < count; i++) {
+ arr.push(Math.floor(i * Math.random() * 10))
+ }
+ return arr
+}
+
+function getNearlyArray(count, swapTime) {
+ const arr = []
+ for (let i = 0; i < count; i++) {
+ arr.push(i)
+ }
+
+ for (let i = 0; i < swapTime; i++) {
+ const x = Math.floor(Math.random() * count)
+ const y = Math.floor(Math.random() * count)
+ swap(arr, x, y)
+ }
+
+ return arr
+}
+
+function getRangedArray(count, min, max) {
+ const arr = []
+ for (let i = 0; i < count; i++) {
+ arr.push(random(min, max))
+ }
+ return arr
+}
+
+function isSorted(target, source) {
+ return (
+ target.toString() ===
+ source
+ .slice()
+ .sort((a, b) => a - b)
+ .toString()
+ )
+}
+
+glob("排序/*.js", (err, result) => {
+ if (err) throw err
+ const sortFunctions = result
+ .map((p) => require(path.resolve(p)))
+ .filter(Boolean)
+ sortTest(sortFunctions, () => getRandomArray(10000), "普通数组排序")
+ sortTest(sortFunctions, () => getNearlyArray(10000), "近似数组排序")
+ sortTest(sortFunctions, () => getRangedArray(500), "大量重复值元素排序")
+})
diff --git "a/\345\267\245\345\205\267/\351\223\276\350\241\250.js" "b/\345\267\245\345\205\267/\351\223\276\350\241\250.js"
new file mode 100644
index 0000000..7479607
--- /dev/null
+++ "b/\345\267\245\345\205\267/\351\223\276\350\241\250.js"
@@ -0,0 +1,25 @@
+function ListNode(val) {
+ this.val = val
+ this.next = null
+}
+
+/**
+ * 数组 -> 链表
+ * @param {number[]} vals
+ */
+function makeListNode(vals) {
+ let head = new ListNode(vals[0])
+ let i = 1
+ let cur = head
+ while (i < vals.length) {
+ let val = vals[i]
+ cur.next = new ListNode(val)
+ cur = cur.next
+ i++
+ }
+ return head
+}
+
+module.exports = ListNode
+
+module.exports.makeListNode = makeListNode
diff --git "a/\345\267\245\345\205\267/\351\232\217\346\234\272\345\200\274.js" "b/\345\267\245\345\205\267/\351\232\217\346\234\272\345\200\274.js"
new file mode 100644
index 0000000..afd8643
--- /dev/null
+++ "b/\345\267\245\345\205\267/\351\232\217\346\234\272\345\200\274.js"
@@ -0,0 +1,5 @@
+function random(low, high) {
+ return Math.round(Math.random() * (high - low)) + low
+}
+
+module.exports = random
diff --git "a/\345\271\277\345\272\246\344\274\230\345\205\210\351\201\215\345\216\206\345\222\214\346\267\261\345\272\246\344\274\230\345\205\210\351\201\215\345\216\206.js" "b/\345\271\277\345\272\246\344\274\230\345\205\210\351\201\215\345\216\206\345\222\214\346\267\261\345\272\246\344\274\230\345\205\210\351\201\215\345\216\206.js"
new file mode 100644
index 0000000..4a17984
--- /dev/null
+++ "b/\345\271\277\345\272\246\344\274\230\345\205\210\351\201\215\345\216\206\345\222\214\346\267\261\345\272\246\344\274\230\345\205\210\351\201\215\345\216\206.js"
@@ -0,0 +1,66 @@
+const data = [
+ {
+ name: "1",
+ children: [
+ {
+ name: "1-1",
+ },
+ {
+ name: "1-2",
+ children: [
+ {
+ name: "1-2-1",
+ },
+ {
+ name: "1-2-2",
+ },
+ ],
+ },
+ {
+ name: "1-3",
+ children: [
+ {
+ name: "1-3-1",
+ },
+ {
+ name: "1-3-2",
+ },
+ ],
+ },
+ ],
+ },
+]
+
+/**
+ * bfs需要借助一个队列,在访问平级节点的时候遇到节点有子节点的话,先全部把子节点推入队列。
+ * 这样下一轮bfs的时候,就会按顺序先平级执行这个队列,在这个过程中重复上一步对子节点的收集。
+ */
+function bfs(tree) {
+ let queue = []
+ tree.forEach((node) => {
+ console.log(node.name)
+ if (node.children) {
+ queue = queue.concat(node.children)
+ }
+ })
+ if (queue.length) {
+ bfs(queue)
+ }
+}
+
+/**
+ * dfs就是一路向下访问,遇到节点有children的情况就直接递归下去,而先不管同级的其他节点。
+ */
+function dfs(tree) {
+ tree.forEach((node) => {
+ console.log(node.name)
+ if (node.children) {
+ dfs(node.children)
+ }
+ })
+}
+
+console.log("bfs")
+bfs(data)
+console.log("dfs")
+dfs(data)
diff --git "a/\347\256\227\346\263\225/\345\275\222\345\271\266\346\216\222\345\272\217.js" "b/\345\275\222\345\271\266\346\216\222\345\272\217.js"
similarity index 64%
rename from "\347\256\227\346\263\225/\345\275\222\345\271\266\346\216\222\345\272\217.js"
rename to "\345\275\222\345\271\266\346\216\222\345\272\217.js"
index 8442c2d..d474b72 100644
--- "a/\347\256\227\346\263\225/\345\275\222\345\271\266\346\216\222\345\272\217.js"
+++ "b/\345\275\222\345\271\266\346\216\222\345\272\217.js"
@@ -1,21 +1,21 @@
function mergeSort(arr) {
- var l = arr.length;
+ let l = arr.length;
if (l === 1) return arr;
- var m = Math.round(l / 2);
- var left = arr.slice(0, m);
- var right = arr.slice(m);
+ let m = Math.round(l / 2);
+ let left = arr.slice(0, m);
+ let right = arr.slice(m);
return merge(mergeSort(left), mergeSort(right));
}
function merge(arr1, arr2) {
- var l1 = arr1.length;
- var l2 = arr2.length;
- var i1 = 0;
- var i2 = 0;
- var r = [];
+ let l1 = arr1.length;
+ let l2 = arr2.length;
+ let i1 = 0;
+ let i2 = 0;
+ let r = [];
while (i1 < l1 && i2 < l2) {
- var item1 = arr1[i1];
- var item2 = arr2[i2];
+ let item1 = arr1[i1];
+ let item2 = arr2[i2];
if (item1 < item2) {
r.push(item1);
i1++;
diff --git "a/\347\256\227\346\263\225/\346\211\276\345\207\272\345\255\220\345\255\227\347\254\246\344\270\262\347\254\254\344\270\200\346\254\241\345\207\272\347\216\260\347\232\204\344\275\215\347\275\256-28.js" "b/\346\211\276\345\207\272\345\255\220\345\255\227\347\254\246\344\270\262\347\254\254\344\270\200\346\254\241\345\207\272\347\216\260\347\232\204\344\275\215\347\275\256-28.js"
similarity index 72%
rename from "\347\256\227\346\263\225/\346\211\276\345\207\272\345\255\220\345\255\227\347\254\246\344\270\262\347\254\254\344\270\200\346\254\241\345\207\272\347\216\260\347\232\204\344\275\215\347\275\256-28.js"
rename to "\346\211\276\345\207\272\345\255\220\345\255\227\347\254\246\344\270\262\347\254\254\344\270\200\346\254\241\345\207\272\347\216\260\347\232\204\344\275\215\347\275\256-28.js"
index 276679d..c2c9594 100644
--- "a/\347\256\227\346\263\225/\346\211\276\345\207\272\345\255\220\345\255\227\347\254\246\344\270\262\347\254\254\344\270\200\346\254\241\345\207\272\347\216\260\347\232\204\344\275\215\347\275\256-28.js"
+++ "b/\346\211\276\345\207\272\345\255\220\345\255\227\347\254\246\344\270\262\347\254\254\344\270\200\346\254\241\345\207\272\347\216\260\347\232\204\344\275\215\347\275\256-28.js"
@@ -3,13 +3,13 @@
* @param {string} needle
* @return {number}
*/
-var strStr = function(haystack, needle) {
+let strStr = function(haystack, needle) {
if (needle === '') return 0
- var start
- for (var i = 0; i < haystack.length - needle.length + 1; i++) {
- for (var j = 0; j < needle.length; j++) {
- var hIndex = i + j
+ let start
+ for (let i = 0; i < haystack.length - needle.length + 1; i++) {
+ for (let j = 0; j < needle.length; j++) {
+ let hIndex = i + j
if (hIndex > haystack.length) {
return -1
}
diff --git "a/\346\216\222\345\272\217/\345\206\222\346\263\241\346\216\222\345\272\217.js" "b/\346\216\222\345\272\217/\345\206\222\346\263\241\346\216\222\345\272\217.js"
new file mode 100644
index 0000000..11e1213
--- /dev/null
+++ "b/\346\216\222\345\272\217/\345\206\222\346\263\241\346\216\222\345\272\217.js"
@@ -0,0 +1,29 @@
+const swap = require("../工具/交换")
+/**
+ * 冒泡排序
+ * @param {number[]} arr
+ */
+function bubbleSort(arr) {
+ let n = arr.length
+ if (n <= 1) return arr
+
+ for (let i = 0; i < n; i++) {
+ let flag = false
+ // 从前往后冒泡 所以已经处理过的就不用再访问了
+ // 并且由于每次遍历会访问j+1项,等于提前遍历了后一项
+ // 所以这里的终止条件可以是n - i再减去1
+ for (let j = 0; j < n - 1 - i; j++) {
+ if (arr[j] > arr[j + 1]) {
+ swap(arr, j, j + 1)
+ flag = true
+ }
+ }
+ // 如果这次循环都没有数字被交换 说明已经是排序好的数组
+ if (!flag) return arr
+ }
+ return arr
+}
+
+bubbleSort.sortName = "冒泡排序"
+
+// module.exports = bubbleSort
diff --git "a/\346\216\222\345\272\217/\345\277\253\351\200\237\346\216\222\345\272\217-\344\270\211\350\267\257.js" "b/\346\216\222\345\272\217/\345\277\253\351\200\237\346\216\222\345\272\217-\344\270\211\350\267\257.js"
new file mode 100644
index 0000000..cab4058
--- /dev/null
+++ "b/\346\216\222\345\272\217/\345\277\253\351\200\237\346\216\222\345\272\217-\344\270\211\350\267\257.js"
@@ -0,0 +1,68 @@
+const swap = require("../工具/交换")
+const random = require("../工具/随机值")
+
+/**
+ * 三路快速排序
+ * 将 arr[l...r] 分为 < v, === v, > v三部分
+ * 之后递归的对 < v, > v 两部分三路快排
+ * @param {number[]} arr
+ */
+function quickSort(arr) {
+ _quickSort(arr, 0, arr.length - 1)
+ return arr
+}
+
+/**
+ * 对 arr[l...r] 部分进行快速排序
+ * @param {number[]} arr
+ * @param {number} l 左边界
+ * @param {number} r 右边界
+ */
+function _quickSort(arr, l, r) {
+ if (l >= r) {
+ return
+ }
+ let [p, q] = partition(arr, l, r)
+ _quickSort(arr, l, p)
+ _quickSort(arr, q, r)
+}
+
+/**
+ * 对 arr[l...r] 部分进行快速排序
+ * @param {number[]} arr
+ * @param {number} l 左边界
+ * @param {number} r 右边界
+ * @returns {number} 返回索引值p,使得arr[l...p-1] < arr[p] < arr[p+1...r]
+ */
+function partition(arr, left, right) {
+ // 取一个基准值 取随机值
+ let rand = random(left, right)
+ swap(arr, left, rand)
+ let pivot = arr[left]
+
+ // 三路 注意看注释里的区间
+ let lt = left // arr[left + 1...lt] < v
+ let gt = right + 1 // arr[gt...r] > v
+ let index = left + 1 // arr[lt + 1...index) === v
+
+ while (index < gt) {
+ let num = arr[index]
+ if (num < pivot) {
+ swap(arr, index, lt + 1)
+ lt++
+ index++
+ } else if (num > pivot) {
+ swap(arr, index, gt - 1)
+ gt--
+ } else if (num === pivot) {
+ index++
+ }
+ }
+ swap(arr, left, lt)
+
+ return [lt - 1, gt]
+}
+
+quickSort.sortName = "快速排序(三路)"
+
+module.exports = quickSort
diff --git "a/\346\216\222\345\272\217/\345\277\253\351\200\237\346\216\222\345\272\217-\347\251\272\351\227\264.js" "b/\346\216\222\345\272\217/\345\277\253\351\200\237\346\216\222\345\272\217-\347\251\272\351\227\264.js"
new file mode 100644
index 0000000..6777d4a
--- /dev/null
+++ "b/\346\216\222\345\272\217/\345\277\253\351\200\237\346\216\222\345\272\217-\347\251\272\351\227\264.js"
@@ -0,0 +1,24 @@
+function quickSort(arr) {
+ if (arr.length === 1 || arr.length === 0) {
+ return arr
+ }
+ const left = []
+
+ const right = []
+ const ref = arr[0]
+
+ for (let i = 1; i < arr.length; i++) {
+ let num = arr[i]
+ if (num < ref) {
+ left.push(num)
+ } else {
+ right.push(num)
+ }
+ }
+
+ return [...quickSort(left), ref, ...quickSort(right)]
+}
+
+quickSort.sortName = "快速排序(空间版)"
+
+// module.exports = quickSort
diff --git "a/\346\216\222\345\272\217/\345\277\253\351\200\237\346\216\222\345\272\217.js" "b/\346\216\222\345\272\217/\345\277\253\351\200\237\346\216\222\345\272\217.js"
new file mode 100644
index 0000000..a6bd467
--- /dev/null
+++ "b/\346\216\222\345\272\217/\345\277\253\351\200\237\346\216\222\345\272\217.js"
@@ -0,0 +1,59 @@
+const swap = require("../工具/交换")
+const random = require("../工具/随机值")
+
+/**
+ *
+ * @param {number[]} arr
+ */
+function quickSort(arr) {
+ _quickSort(arr, 0, arr.length - 1)
+ return arr
+}
+
+/**
+ * 对 arr[l...r] 部分进行快速排序
+ * @param {number[]} arr
+ * @param {number} l 左边界
+ * @param {number} r 右边界
+ */
+function _quickSort(arr, l, r) {
+ if (l >= r) {
+ return
+ }
+ let p = partition(arr, l, r)
+ _quickSort(arr, l, p - 1)
+ _quickSort(arr, p + 1, r)
+}
+
+/**
+ * 对 arr[l...r] 部分进行快速排序
+ * @param {number[]} arr
+ * @param {number} l 左边界
+ * @param {number} r 右边界
+ * @returns {number} 返回索引值p,使得arr[l...p-1] < arr[p] < arr[p+1...r]
+ */
+function partition(arr, left, right) {
+ // 取一个基准值 取随机值
+ let rand = random(left, right)
+ swap(arr, left, rand)
+ let pivot = arr[left]
+
+ // arr[left+1...index] < pivot, arr[index+1...i) > pivot
+ let index = left
+ for (let i = left + 1; i <= right; i++) {
+ let num = arr[i]
+ if (num < pivot) {
+ // 如果当前值小于基准值的话,就交换到index + 1的位置去。
+ // 扩充了index的范围 [index...], pivot, [...right]
+ swap(arr, index + 1, i)
+ index++
+ }
+ }
+
+ swap(arr, left, index)
+ return index
+}
+
+quickSort.sortName = "快速排序"
+
+// module.exports = quickSort
diff --git "a/\346\216\222\345\272\217/\351\200\211\346\213\251\346\216\222\345\272\217.js" "b/\346\216\222\345\272\217/\351\200\211\346\213\251\346\216\222\345\272\217.js"
new file mode 100644
index 0000000..54e1ce7
--- /dev/null
+++ "b/\346\216\222\345\272\217/\351\200\211\346\213\251\346\216\222\345\272\217.js"
@@ -0,0 +1,18 @@
+const swap = require("../工具/交换")
+
+function selectSort(arr) {
+ for (let i = 0; i < arr.length; i++) {
+ let min = i
+ for (let j = i + 1; j < arr.length; j++) {
+ if (arr[j] < arr[min]) {
+ min = j
+ }
+ }
+ swap(arr, i, min)
+ }
+ return arr
+}
+
+selectSort.sortName = "选择排序"
+
+// module.exports = selectSort
diff --git "a/\347\256\227\346\263\225/\346\234\200\351\225\277\345\205\254\345\205\261\345\211\215\347\274\200.js" "b/\346\234\200\351\225\277\345\205\254\345\205\261\345\211\215\347\274\200.js"
similarity index 77%
rename from "\347\256\227\346\263\225/\346\234\200\351\225\277\345\205\254\345\205\261\345\211\215\347\274\200.js"
rename to "\346\234\200\351\225\277\345\205\254\345\205\261\345\211\215\347\274\200.js"
index 3cd3d29..5554471 100644
--- "a/\347\256\227\346\263\225/\346\234\200\351\225\277\345\205\254\345\205\261\345\211\215\347\274\200.js"
+++ "b/\346\234\200\351\225\277\345\205\254\345\205\261\345\211\215\347\274\200.js"
@@ -2,11 +2,11 @@
* @param {string[]} strs
* @return {string}
*/
-var longestCommonPrefix = function (strs) {
- var point = 0
- var common = ""
- var shortestStr
- var getShortestStr = false
+let longestCommonPrefix = function (strs) {
+ let point = 0
+ let common = ""
+ let shortestStr
+ let getShortestStr = false
if (strs.length === 1) {
return strs[0]
@@ -16,8 +16,8 @@ var longestCommonPrefix = function (strs) {
}
while (1) {
- for (var i = 0; i < strs.length; i++) {
- var str = strs[i]
+ for (let i = 0; i < strs.length; i++) {
+ let str = strs[i]
if (i > 0 && str[point] !== strs[i - 1][point]) {
return common
}
diff --git "a/\346\234\211\345\272\217\346\225\260\347\273\204\346\261\202\344\272\244\351\233\206.js" "b/\346\234\211\345\272\217\346\225\260\347\273\204\346\261\202\344\272\244\351\233\206.js"
new file mode 100644
index 0000000..555d2e4
--- /dev/null
+++ "b/\346\234\211\345\272\217\346\225\260\347\273\204\346\261\202\344\272\244\351\233\206.js"
@@ -0,0 +1,79 @@
+let a = []
+
+for (let index = 0; index < 500; index++) {
+ a.push(i)
+}
+
+for (let i = 16; i < 10000; i++) {
+ a.push(i)
+}
+
+let b = []
+
+for (let index = 0; index < 500; index++) {
+ b.push(i)
+}
+
+for (let i = 10001; i < 50000; i++) {
+ b.push(i)
+}
+
+function mapIntersection(arr1, arr2) {
+ console.time()
+ let map = new Map()
+ for (let i = 0; i < arr1.length; i++) {
+ map.set(arr1[i], true)
+ }
+
+ let result = []
+ for (let i = 0; i < arr2.length; i++) {
+ let val = arr2[i]
+ if (map.get(val)) {
+ result.push(val)
+ }
+ }
+ console.timeEnd()
+ return result
+}
+
+console.log("mapIntersection", mapIntersection(a, b))
+
+function pointIntersection(arr1, arr2) {
+ console.time()
+ let i = 0
+ let j = 0
+
+ let l1 = arr1.length
+ let l2 = arr2.length
+
+ let result = []
+ while (i < l1 && j < l2) {
+ let val1 = arr1[i]
+ let val2 = arr2[j]
+ let val1Last = arr1[i - 1]
+ let val2Last = arr2[j - 1]
+
+ if (val1 > val2) {
+ i++
+ }
+
+ if (val1 === val2) {
+ result.push(val1)
+ i++
+ j++
+ }
+
+ if (val1 < val2) {
+ j++
+ }
+
+ if (val1 > val2Last || val2 > val1Last) {
+ console.timeEnd()
+ return result
+ }
+ }
+ console.timeEnd()
+ return result
+}
+
+console.log('pointIntersection', pointIntersection(a, b))
\ No newline at end of file
diff --git "a/\346\234\211\345\272\217\346\225\260\347\273\204\347\232\204\345\215\225\344\270\252\345\205\203\347\264\240-540.js" "b/\346\234\211\345\272\217\346\225\260\347\273\204\347\232\204\345\215\225\344\270\252\345\205\203\347\264\240-540.js"
new file mode 100644
index 0000000..bb30ae6
--- /dev/null
+++ "b/\346\234\211\345\272\217\346\225\260\347\273\204\347\232\204\345\215\225\344\270\252\345\205\203\347\264\240-540.js"
@@ -0,0 +1,61 @@
+/**
+ 540. 有序数组中的单一元素
+ 给定一个只包含整数的有序数组,每个元素都会出现两次,唯有一个数只会出现一次,找出这个数。
+
+ 示例 1:
+
+ 输入: [1,1,2,3,3,4,4,8,8]
+ 输出: 2
+ 示例 2:
+
+ 输入: [3,3,7,7,10,11,11]
+ 输出: 10
+ 注意: 您的方案应该在 O(log n)时间复杂度和 O(1)空间复杂度中运行。
+ */
+
+function singleNonDuplicate(nums) {
+ let len = nums.length
+
+ let lo = 0
+ let hi = len - 1
+
+ while (lo < hi) {
+ let mid = lo + Math.floor((hi - lo) / 2)
+ let midVal = nums[mid]
+
+ // 被mid后的数组长度是奇数还是偶数
+ let halvesAreEven = (hi - mid) % 2 == 0;
+ if (midVal === nums[mid - 1]) {
+ if (halvesAreEven) {
+ // [0, 1, 1, 2, 2]
+ // mid
+ // 显然左边是奇数 [0] hi是mid往左两位
+ hi = mid - 2
+ }else {
+ // [0, 0, 1, 1, 2, 2, 3]
+ // mid
+ // 显然右边是奇数 [2, 2, 3] lo是mid往右一位
+ lo = mid + 1
+ }
+
+ }else if (midVal === nums[mid + 1]) {
+ if (halvesAreEven) {
+ // [0, 0, 1, 1, 2]
+ // mid
+ // 右边是奇数 [2] lo是mid右移动两位
+ lo = mid + 2
+ }else {
+ // [0, 0, 1, 2, 2, 3, 3]
+ // mid
+ // 左边是奇数 [0, 0, 1] hi是mid左移一位
+ hi = mid - 1
+ }
+ } else {
+ return midVal
+ }
+ }
+ return nums[lo]
+}
+
+
+console.log(singleNonDuplicate([3,3,7,7,10,11,11]))
\ No newline at end of file
diff --git "a/\346\234\211\345\272\217\347\237\251\351\230\265\344\270\255\347\254\254K\345\260\217\347\232\204\345\205\203\347\264\240-378.js" "b/\346\234\211\345\272\217\347\237\251\351\230\265\344\270\255\347\254\254K\345\260\217\347\232\204\345\205\203\347\264\240-378.js"
new file mode 100644
index 0000000..6ce08fc
--- /dev/null
+++ "b/\346\234\211\345\272\217\347\237\251\351\230\265\344\270\255\347\254\254K\345\260\217\347\232\204\345\205\203\347\264\240-378.js"
@@ -0,0 +1,31 @@
+/**
+ * @param {number[][]} matrix
+ * @param {number} k
+ * @return {number}
+ */
+let kthSmallest = function (matrix, k) {
+ let maxY = matrix.length
+ let sorted = []
+ let points = []
+ for (let i = 0; i < maxY; i++) {
+ points[i] = 0
+ }
+
+ while (sorted.length < k) {
+ let min = Infinity
+ let minY
+ for (let y = 0; y < maxY; y++) {
+ let point = points[y]
+ let num = matrix[y][point]
+ if (num < min) {
+ min = num
+ minY = y
+ }
+ }
+ sorted.push(min)
+ // 选中最小项的x指针右移
+ points[minY]++
+ }
+
+ return sorted[sorted.length - 1]
+};
\ No newline at end of file
diff --git "a/\346\240\207\351\242\230\345\210\206\347\273\204.js" "b/\346\240\207\351\242\230\345\210\206\347\273\204.js"
new file mode 100644
index 0000000..8bd5c54
--- /dev/null
+++ "b/\346\240\207\351\242\230\345\210\206\347\273\204.js"
@@ -0,0 +1,105 @@
+/**
+ 需要输出
+ [{
+ "name": "h3"
+ }, {
+ "name": "h2",
+ "child": [{
+ "name": "h3"
+ }]
+ }, {
+ "name": "h1",
+ "child": [{
+ "name": "h2",
+ "child": [{
+ "name": "h3"
+ }, {
+ "name": "h3"
+ }]
+ }, {
+ "name": "h2",
+ "child": [{
+ "name": "h3"
+ }]
+ }]
+ }, {
+ "name": "h1",
+ "child": [{
+ "name": "h2",
+ "child": [{
+ "name": "h4"
+ }]
+ }, {
+ "name": "h2",
+ "child": [{
+ "name": "h3"
+ }]
+ }]
+ }]
+ */
+
+let list = [
+ 'h3',
+ 'h2', 'h3',
+ 'h1', 'h2', 'h3', 'h3', 'h2', 'h3',
+ 'h1', 'h2', 'h4', 'h2', 'h3'
+]
+
+function makeTree(arr) {
+ let tree = [];
+ let max = Infinity
+ let prev = {};
+
+ arr.forEach((title) => {
+ let level = Number(title[1]);
+ if (level <= max) {
+ let node = {
+ name: title,
+ };
+ tree.push(node);
+ prev.level = level;
+ prev.node = node;
+ max = level
+ } else if (level === prev.level) {
+ // 等级相同的话 上级节点的child继续增加子节点
+ prev = prev.prev;
+ pushNodeAndAdvanceQueue();
+ } else if (level > prev.level) {
+ pushNodeAndAdvanceQueue();
+ } else {
+ while (level <= prev.level) {
+ // 向上回溯,找到平级的再上一层node
+ prev = prev.prev;
+ }
+ pushNodeAndAdvanceQueue();
+ }
+
+ function pushNodeAndAdvanceQueue() {
+ let node = {
+ name: title,
+ };
+ if (!prev.node.child) {
+ let child = [];
+ prev.node.child = child;
+ }
+ prev.node.child.push(node);
+ let next = {
+ level,
+ node,
+ prev,
+ };
+ prev = next;
+ }
+ });
+
+ return tree;
+}
+
+console.log(makeTree(list));
+
+/**
+ * 思路
+ *
+ * 利用链表来向上回溯合适的父节点
+ * 利用max变量记录当前分组的最大标题,如果比max还大,就需要新开一个分组了。
+ */
diff --git "a/\346\240\210\345\222\214\351\230\237\345\210\227/\344\272\214\345\217\211\346\240\221\347\232\204\345\211\215\345\272\217\351\201\215\345\216\206-144.js" "b/\346\240\210\345\222\214\351\230\237\345\210\227/\344\272\214\345\217\211\346\240\221\347\232\204\345\211\215\345\272\217\351\201\215\345\216\206-144.js"
new file mode 100644
index 0000000..ee7bca5
--- /dev/null
+++ "b/\346\240\210\345\222\214\351\230\237\345\210\227/\344\272\214\345\217\211\346\240\221\347\232\204\345\211\215\345\272\217\351\201\215\345\216\206-144.js"
@@ -0,0 +1,47 @@
+const TreeNode = require("../工具/二叉树")
+
+/**
+ * @param {TreeNode} root
+ * @return {number[]}
+ */
+let preorderTraversal = function (root) {
+ let res = []
+ let stack = [
+ {
+ type: "go",
+ node: root,
+ },
+ ]
+
+ while (stack.length) {
+ let { type, node } = stack.pop()
+
+ if (!node) continue
+
+ if (type === "print") {
+ res.push(node.val)
+ }
+
+ if (type === "go") {
+ stack.push({ type: "print", node })
+
+ if (node.right) {
+ stack.push({ type: "go", node: node.right })
+ }
+
+ if (node.left) {
+ stack.push({ type: "go", node: node.left })
+ }
+ }
+ }
+
+ return res
+}
+
+const tree = new TreeNode(1)
+tree.left = new TreeNode(4)
+tree.left.left = new TreeNode(5)
+tree.right = new TreeNode(6)
+tree.right.right = new TreeNode(7)
+
+console.log(preorderTraversal(tree))
diff --git "a/\346\240\210\345\222\214\351\230\237\345\210\227/\344\273\216\344\270\212\345\210\260\344\270\213\346\211\223\345\215\260\344\272\214\345\217\211\346\240\221III-\351\235\242\350\257\225\351\242\23032.js" "b/\346\240\210\345\222\214\351\230\237\345\210\227/\344\273\216\344\270\212\345\210\260\344\270\213\346\211\223\345\215\260\344\272\214\345\217\211\346\240\221III-\351\235\242\350\257\225\351\242\23032.js"
new file mode 100644
index 0000000..62b4b41
--- /dev/null
+++ "b/\346\240\210\345\222\214\351\230\237\345\210\227/\344\273\216\344\270\212\345\210\260\344\270\213\346\211\223\345\215\260\344\272\214\345\217\211\346\240\221III-\351\235\242\350\257\225\351\242\23032.js"
@@ -0,0 +1,39 @@
+const TreeNode = require("../工具/二叉树")
+
+let levelOrder = function (root) {
+ let queue = [root]
+ let res = []
+ if (!root) return res
+ let level = 0
+ while (queue.length) {
+ level++
+ let subRes = []
+ let len = queue.length
+ let shouldReverse = level % 2 === 0
+
+ for (let i = 0; i < len; i++) {
+ let node = queue.shift()
+ subRes.push(node.val)
+ if (node.left) {
+ queue.push(node.left)
+ }
+ if (node.right) {
+ queue.push(node.right)
+ }
+ }
+ // 偶数行 把结果子数组reverse即可
+ if (shouldReverse) {
+ subRes.reverse()
+ }
+ res.push(subRes)
+ }
+ return res
+}
+
+let tree = new TreeNode(1)
+tree.left = new TreeNode(2)
+tree.left.left = new TreeNode(4)
+tree.right = new TreeNode(3)
+tree.right.right = new TreeNode(5)
+
+console.log(levelOrder(tree))
diff --git "a/\346\240\210\345\222\214\351\230\237\345\210\227/\346\234\211\346\225\210\347\232\204\346\213\254\345\217\267-20.js" "b/\346\240\210\345\222\214\351\230\237\345\210\227/\346\234\211\346\225\210\347\232\204\346\213\254\345\217\267-20.js"
new file mode 100644
index 0000000..b02a587
--- /dev/null
+++ "b/\346\240\210\345\222\214\351\230\237\345\210\227/\346\234\211\346\225\210\347\232\204\346\213\254\345\217\267-20.js"
@@ -0,0 +1,52 @@
+/**
+ * @param {string} s
+ * @return {boolean}
+ */
+let isValid = function (s) {
+ let sl = s.length
+ if (sl % 2 !== 0) return false
+ let leftToRight = {
+ "{": "}",
+ "[": "]",
+ "(": ")",
+ }
+ // 建立一个反向的 value -> key 映射表
+ let rightToLeft = createReversedMap(leftToRight)
+ // 用来匹配左右括号的栈
+ let stack = []
+
+ for (let i = 0; i < s.length; i++) {
+ let bracket = s[i]
+ // 左括号 放进栈中
+ if (leftToRight[bracket]) {
+ stack.push(bracket)
+ } else {
+ let needLeftBracket = rightToLeft[bracket]
+ // 左右括号都不是 直接失败
+ if (!needLeftBracket) {
+ return false
+ }
+
+ // 栈中取出最后一个括号 如果不是需要的那个左括号 就失败
+ let lastBracket = stack.pop()
+ if (needLeftBracket !== lastBracket) {
+ return false
+ }
+ }
+ }
+
+ if (stack.length) {
+ return false
+ }
+ return true
+}
+
+function createReversedMap(map) {
+ return Object.keys(map).reduce((prev, key) => {
+ const value = map[key]
+ prev[value] = key
+ return prev
+ }, {})
+}
+
+console.log(isValid('({})[()]'))
\ No newline at end of file
diff --git "a/\346\240\210\345\222\214\351\230\237\345\210\227/\347\256\200\345\214\226\350\267\257\345\276\204-71.js" "b/\346\240\210\345\222\214\351\230\237\345\210\227/\347\256\200\345\214\226\350\267\257\345\276\204-71.js"
new file mode 100644
index 0000000..caed5c7
--- /dev/null
+++ "b/\346\240\210\345\222\214\351\230\237\345\210\227/\347\256\200\345\214\226\350\267\257\345\276\204-71.js"
@@ -0,0 +1,33 @@
+/**
+ * @param {string} path
+ * @return {string}
+ */
+let simplifyPath = function (path) {
+ let tokens = path.split("/")
+ let stack = []
+
+ for (let index = 0; index < tokens.length; index++) {
+ let token = tokens[index]
+ if (token === "..") {
+ if (stack.length > 0) {
+ stack.pop()
+ }
+ } else if (!(token === '') && !(token === '.')) {
+ stack.push(token)
+ }
+ }
+
+ let res = '/'
+
+ for (let token of stack) {
+ res += `${token}/`
+ }
+
+ if (res !== '/') {
+ res = res.substr(0, res.length - 1)
+ }
+
+ return res
+}
+
+console.log(simplifyPath("/home/"))
diff --git "a/\346\240\210\345\222\214\351\230\237\345\210\227/\351\200\206\346\263\242\345\205\260\350\241\250\350\276\276\345\274\217\346\261\202\345\200\274-150.js" "b/\346\240\210\345\222\214\351\230\237\345\210\227/\351\200\206\346\263\242\345\205\260\350\241\250\350\276\276\345\274\217\346\261\202\345\200\274-150.js"
new file mode 100644
index 0000000..5b9fcec
--- /dev/null
+++ "b/\346\240\210\345\222\214\351\230\237\345\210\227/\351\200\206\346\263\242\345\205\260\350\241\250\350\276\276\345\274\217\346\261\202\345\200\274-150.js"
@@ -0,0 +1,28 @@
+/**
+ * @param {string[]} tokens
+ * @return {number}
+ */
+let opMap = {
+ "+": (a, b) => b + a,
+ "-": (a, b) => b - a,
+ "*": (a, b) => b * a,
+ "/": (a, b) => parseInt(b / a, 10),
+}
+
+let evalRPN = function (tokens) {
+ let stack = []
+ for (let token of tokens) {
+ let op = opMap[token]
+ if (op) {
+ let a = parseInt(stack.pop())
+ let b = parseInt(stack.pop())
+ let res = op(a, b)
+ stack.push(res)
+ } else {
+ stack.push(token)
+ }
+ }
+ return stack[0]
+}
+
+console.log(evalRPN(["-8","23","8","-","9","23","-","-","*","33","-8","/","+","38","-14","-","-","-7","32","-19","-","11","+","+","+","14","22","-","-","27","-9","-","+","31","+","-12","-11","-","-","14","+","30","+","37","30","-","+","-9","+","7","-","37","+","-5","13","/","-","19","-2","-19","12","+","-","23","+","-","-19","-","+","6","+","-17","+","17","+","5","36","+","-10","+","+","23","-8","-","-","18","-","31","-16","-","+","34","+","-6","+","24","-","22","-","-8","-","28","+","-12","+","39","28","-7","+","+","-14","5","+","5","+","10","+","+","+","-18","*","10","+","-5","11","-","6","+","-","-12","31","+","+","30","29","-","-","39","+","13","-8","-5","+","-","26","19","-","*","-","10","-","-20","5","+","+","0","-","28","-","19","/","28","+","-18","-","28","20","+","-5","-19","+","+","-","-12","-","3","-","6","-15","+","4","-","-","38","+","-9","-","38","-","12","-20","-","10","5","-15","-","-","-","+","-11","+","5","+","2","-","28","+","-9","-11","-","+","37","-","-17","31","-","2","+","+","-16","-12","-","-","12","+","34","-","15","+","8","+","17","-","2","-","33","+","-5","+","14","+","29","-","33","23","+","26","30","-","+","+","39","+","9","24","-","-","20","15","+","-","24","+","37","-","30","-1","-","+","34","+","-13","-","23","15","-","-","-5","-8","8","30","35","-9","22","+","-","-","36","-1","+","5","-","-","+","25","-","+","27","-","16","+","+","+","39","-","15","-","-3","+","5","-6","-","+","-6","-15","-7","-","+","/","13","-","18","+","4","+","29","+","-17","0","-6","-20","-17","+","12","-","+","-","+","+","-10","22","+","+","-11","-","-2","38","-","-","-6","+","0","-","-10","+","-4","-10","+","-","0","-","31","30","-","37","5","+","+","+","-15","+","38","4","-","-16","-17","+","+","+","38","-","27","-19","/","12","+","/"]))
diff --git "a/\347\256\227\346\263\225/\346\240\274\351\233\267\347\274\226\347\240\201.js" "b/\346\240\274\351\233\267\347\274\226\347\240\201.js"
similarity index 94%
rename from "\347\256\227\346\263\225/\346\240\274\351\233\267\347\274\226\347\240\201.js"
rename to "\346\240\274\351\233\267\347\274\226\347\240\201.js"
index e158ac2..bbc7aab 100644
--- "a/\347\256\227\346\263\225/\346\240\274\351\233\267\347\274\226\347\240\201.js"
+++ "b/\346\240\274\351\233\267\347\274\226\347\240\201.js"
@@ -2,7 +2,7 @@
* @param {number} n
* @return {number[]}
*/
-var grayCode = function(n) {
+let grayCode = function(n) {
// 用来算输入为n的格雷编码序列
let make = n => {
if (n === 1) {
diff --git "a/\346\273\221\345\212\250\347\252\227\345\217\243/\346\211\276\345\210\260\345\255\227\347\254\246\344\270\262\344\270\255\346\211\200\346\234\211\345\255\227\346\257\215\345\274\202\344\275\215\350\257\215-438.js" "b/\346\273\221\345\212\250\347\252\227\345\217\243/\346\211\276\345\210\260\345\255\227\347\254\246\344\270\262\344\270\255\346\211\200\346\234\211\345\255\227\346\257\215\345\274\202\344\275\215\350\257\215-438.js"
new file mode 100644
index 0000000..d1b1485
--- /dev/null
+++ "b/\346\273\221\345\212\250\347\252\227\345\217\243/\346\211\276\345\210\260\345\255\227\347\254\246\344\270\262\344\270\255\346\211\200\346\234\211\345\255\227\346\257\215\345\274\202\344\275\215\350\257\215-438.js"
@@ -0,0 +1,59 @@
+/**
+ * @param {string} s
+ * @param {string} p
+ * @return {number[]}
+ */
+let findAnagrams = function (s, p) {
+ let targetMap = makeCountMap(p)
+ let sl = s.length
+ let pl = p.length
+ // [left,...right] 滑动窗口
+ let left = 0
+ let right = pl - 1
+ let windowMap = makeCountMap(s.substring(left, right + 1))
+ let res = []
+
+ while (left <= sl - pl && right < sl) {
+ if (isAnagrams(windowMap, targetMap)) {
+ res.push(left)
+ }
+ windowMap[s[left]]--
+ right++
+ left++
+ addCountToMap(windowMap, s[right])
+ }
+
+ return res
+}
+
+let isAnagrams = function (windowMap, targetMap) {
+ let targetKeys = Object.keys(targetMap)
+ for (let targetKey of targetKeys) {
+ if (
+ !windowMap[targetKey] ||
+ windowMap[targetKey] !== targetMap[targetKey]
+ ) {
+ return false
+ }
+ }
+ return true
+}
+
+function addCountToMap(map, str) {
+ if (!map[str]) {
+ map[str] = 1
+ } else {
+ map[str]++
+ }
+}
+
+function makeCountMap(strs) {
+ let map = {}
+ for (let i = 0; i < strs.length; i++) {
+ let letter = strs[i]
+ addCountToMap(map, letter)
+ }
+ return map
+}
+
+console.log(findAnagrams("abab", "ab"))
diff --git "a/\346\273\221\345\212\250\347\252\227\345\217\243/\346\227\240\351\207\215\345\244\215\345\255\227\347\254\246\347\232\204\346\234\200\351\225\277\345\255\220\344\270\262-3.js" "b/\346\273\221\345\212\250\347\252\227\345\217\243/\346\227\240\351\207\215\345\244\215\345\255\227\347\254\246\347\232\204\346\234\200\351\225\277\345\255\220\344\270\262-3.js"
new file mode 100644
index 0000000..84cbb59
--- /dev/null
+++ "b/\346\273\221\345\212\250\347\252\227\345\217\243/\346\227\240\351\207\215\345\244\215\345\255\227\347\254\246\347\232\204\346\234\200\351\225\277\345\255\220\344\270\262-3.js"
@@ -0,0 +1,28 @@
+/**
+ * @param {string} s
+ * @return {number}
+ */
+let lengthOfLongestSubstring = function (str) {
+ let n = str.length
+ // 滑动窗口为s[left...right]
+ let left = 0
+ let right = -1
+ let freqMap = {} // 记录当前子串中下标对应的出现频率
+ let max = 0 // 找到的满足条件子串的最长长度
+
+ while (left < n) {
+ let nextLetter = str[right + 1]
+ if (!freqMap[nextLetter] && nextLetter !== undefined) {
+ freqMap[nextLetter] = 1
+ right++
+ } else {
+ freqMap[str[left]] = 0
+ left++
+ }
+ max = Math.max(max, right - left + 1)
+ }
+
+ return max
+}
+
+console.log(lengthOfLongestSubstring("pwwkew"))
\ No newline at end of file
diff --git "a/\346\273\221\345\212\250\347\252\227\345\217\243/\346\234\200\345\260\217\350\246\206\347\233\226\345\255\220\344\270\262.js" "b/\346\273\221\345\212\250\347\252\227\345\217\243/\346\234\200\345\260\217\350\246\206\347\233\226\345\255\220\344\270\262.js"
new file mode 100644
index 0000000..e855d8e
--- /dev/null
+++ "b/\346\273\221\345\212\250\347\252\227\345\217\243/\346\234\200\345\260\217\350\246\206\347\233\226\345\255\220\344\270\262.js"
@@ -0,0 +1,65 @@
+/**
+ * @param {string} s
+ * @param {string} t
+ * @return {string}
+ */
+let minWindow = function (s, t) {
+ // 先制定目标 根据t字符串统计出每个字符应该出现的个数
+ let targetMap = makeCountMap(t)
+
+ let sl = s.length
+ let tl = t.length
+ let left = 0 // 左边界
+ let right = -1 // 右边界
+ let countMap = {} // 当前窗口子串中 每个字符出现的次数
+ let min = "" // 当前计算出的最小子串
+
+ // 循环终止条件是两者有一者超出边界
+ while (left <= sl - tl && right <= sl) {
+ // 和 targetMap 对比出现次数 确定是否满足条件
+ let isValid = true
+ Object.keys(targetMap).forEach((key) => {
+ let targetCount = targetMap[key]
+ let count = countMap[key]
+ if (!count || count < targetCount) {
+ isValid = false
+ }
+ })
+
+ if (isValid) {
+ // 如果满足 记录当前的子串 并且左边界右移
+ let currentValidLength = right - left + 1
+ if (currentValidLength < min.length || min === "") {
+ min = s.substring(left, right + 1)
+ }
+ // 也要把map里对应的项去掉
+ countMap[s[left]]--
+ left++
+ } else {
+ // 否则右边界右移
+ addCountToMap(countMap, s[right + 1])
+ right++
+ }
+ }
+
+ return min
+}
+
+function addCountToMap(map, str) {
+ if (!map[str]) {
+ map[str] = 1
+ } else {
+ map[str]++
+ }
+}
+
+function makeCountMap(strs) {
+ let map = {}
+ for (let i = 0; i < strs.length; i++) {
+ let letter = strs[i]
+ addCountToMap(map, letter)
+ }
+ return map
+}
+
+console.log(minWindow("aa", "a"))
diff --git "a/\346\273\221\345\212\250\347\252\227\345\217\243/\346\273\221\345\212\250\347\252\227\345\217\243\347\232\204\346\234\200\345\244\247\345\200\274-\351\235\242\350\257\225\351\242\23059 - I.js" "b/\346\273\221\345\212\250\347\252\227\345\217\243/\346\273\221\345\212\250\347\252\227\345\217\243\347\232\204\346\234\200\345\244\247\345\200\274-\351\235\242\350\257\225\351\242\23059 - I.js"
new file mode 100644
index 0000000..f2c51cf
--- /dev/null
+++ "b/\346\273\221\345\212\250\347\252\227\345\217\243/\346\273\221\345\212\250\347\252\227\345\217\243\347\232\204\346\234\200\345\244\247\345\200\274-\351\235\242\350\257\225\351\242\23059 - I.js"
@@ -0,0 +1,24 @@
+let maxSlidingWindow = function (nums, k) {
+ if (k === 0 || !nums.length) {
+ return []
+ }
+ let left = 0
+ let right = k - 1
+ let res = [findMax(nums, left, right)]
+
+ while (right < nums.length - 1) {
+ right++
+ left++
+ res.push(findMax(nums, left, right))
+ }
+
+ return res
+}
+
+function findMax(nums, left, right) {
+ let max = -Infinity
+ for (let i = left; i <= right; i++) {
+ max = Math.max(max, nums[i])
+ }
+ return max
+}
\ No newline at end of file
diff --git "a/\346\273\221\345\212\250\347\252\227\345\217\243/\351\225\277\345\272\246\346\234\200\345\260\217\347\232\204\345\255\220\346\225\260\347\273\204-209.js" "b/\346\273\221\345\212\250\347\252\227\345\217\243/\351\225\277\345\272\246\346\234\200\345\260\217\347\232\204\345\255\220\346\225\260\347\273\204-209.js"
new file mode 100644
index 0000000..bd05c78
--- /dev/null
+++ "b/\346\273\221\345\212\250\347\252\227\345\217\243/\351\225\277\345\272\246\346\234\200\345\260\217\347\232\204\345\255\220\346\225\260\347\273\204-209.js"
@@ -0,0 +1,30 @@
+/**
+ * @param {number} s
+ * @param {number[]} nums
+ * @return {number}
+ */
+let minSubArrayLen = function (s, nums) {
+ let n = nums.length
+ // 定义[i,...j]滑动窗口 取这个窗口里的和
+ let i = 0
+ let j = -1
+
+ let sum = 0
+ let res = Infinity
+
+ while (i < n) {
+ if (sum < s) {
+ sum += nums[++j]
+ } else {
+ sum -= nums[i]
+ i++
+ }
+
+ if (sum >= s) {
+ res = Math.min(res, j - i + 1)
+ }
+ }
+ return res === Infinity ? 0 : res
+}
+
+console.log(minSubArrayLen(7, [2, 3, 1, 2, 4, 3]))
diff --git "a/\347\256\227\346\263\225/\347\247\215\350\212\261\351\227\256\351\242\230.js" "b/\347\247\215\350\212\261\351\227\256\351\242\230.js"
similarity index 90%
rename from "\347\256\227\346\263\225/\347\247\215\350\212\261\351\227\256\351\242\230.js"
rename to "\347\247\215\350\212\261\351\227\256\351\242\230.js"
index 7938777..f8ed412 100644
--- "a/\347\256\227\346\263\225/\347\247\215\350\212\261\351\227\256\351\242\230.js"
+++ "b/\347\247\215\350\212\261\351\227\256\351\242\230.js"
@@ -23,12 +23,12 @@
* @param {number} n
* @return {boolean}
*/
-var canPlaceFlowers = function(flowerbed, n) {
+let canPlaceFlowers = function(flowerbed, n) {
// empty代表连续命中0的次数 命中3次就说明要回退一个种花
- var empty = 1
- var count = 0
- for (var i = 0; i < flowerbed.length; i++) {
- var has = flowerbed[i]
+ let empty = 1
+ let count = 0
+ for (let i = 0; i < flowerbed.length; i++) {
+ let has = flowerbed[i]
if (!has) {
empty++
// 连续三次空白
diff --git "a/\347\256\227\346\263\225/\347\247\273\345\212\250\351\233\266-283.js" "b/\347\247\273\345\212\250\351\233\266-283.js"
similarity index 90%
rename from "\347\256\227\346\263\225/\347\247\273\345\212\250\351\233\266-283.js"
rename to "\347\247\273\345\212\250\351\233\266-283.js"
index 3aa4fae..deae007 100644
--- "a/\347\256\227\346\263\225/\347\247\273\345\212\250\351\233\266-283.js"
+++ "b/\347\247\273\345\212\250\351\233\266-283.js"
@@ -44,11 +44,11 @@
* @param {number[]} nums
* @return {void} Do not return anything, modify nums in-place instead.
*/
-var moveZeroes = function(nums) {
- var j = 0
- for (var i = 0; i < nums.length; i++) {
+let moveZeroes = function(nums) {
+ let j = 0
+ for (let i = 0; i < nums.length; i++) {
if (nums[i] !== 0) {
- var temp = nums[j]
+ let temp = nums[j]
nums[j] = nums[i]
nums[i] = temp
j++
diff --git "a/\347\247\273\351\231\244\345\205\203\347\264\240.js" "b/\347\247\273\351\231\244\345\205\203\347\264\240.js"
new file mode 100644
index 0000000..2c89cec
--- /dev/null
+++ "b/\347\247\273\351\231\244\345\205\203\347\264\240.js"
@@ -0,0 +1,53 @@
+/**
+ 给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。
+
+ 不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。
+
+ 元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
+
+
+
+ 示例 1:
+
+ 给定 nums = [3,2,2,3], val = 3,
+
+ 函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。
+
+ 你不需要考虑数组中超出新长度后面的元素。
+ 示例 2:
+
+ 给定 nums = [0,1,2,2,3,0,4,2], val = 2,
+
+ 函数应该返回新的长度 5, 并且 nums 中的前五个元素为 0, 1, 3, 0, 4。
+
+ 注意这五个元素可为任意顺序。
+
+ 你不需要考虑数组中超出新长度后面的元素。
+
+ 来源:力扣(LeetCode)
+ 链接:https://leetcode-cn.com/problems/remove-element
+ 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
+ */
+
+let removeElement = function (nums, val) {
+ let i = 0;
+ let j = 0;
+
+ while (i < nums.length) {
+ let num = nums[i];
+ if (num !== val) {
+ nums[j] = num;
+ j++;
+ }
+
+ i++;
+ }
+
+ return j;
+};
+
+removeElement([3, 2, 2, 3], 3);
+
+/**
+ * 这题用的是双指针法,慢指针指向待替换的位置,等到读取到非目标值的时候,就替换到那个位置,然后把慢指针前进。
+ */
diff --git "a/\347\256\227\346\263\225/longest-prefix.js" "b/\347\256\227\346\263\225/longest-prefix.js"
deleted file mode 100644
index 389f83e..0000000
--- "a/\347\256\227\346\263\225/longest-prefix.js"
+++ /dev/null
@@ -1,43 +0,0 @@
-/**
- * 「快乐前缀」是在原字符串中既是 非空 前缀也是后缀(不包括原字符串自身)的字符串。
-
- 给你一个字符串 s,请你返回它的 最长快乐前缀。
-
- 如果不存在满足题意的前缀,则返回一个空字符串。
-
- 示例:
-
- 输入:s = 'level'
-
- 输出:'l'
-
- 解释:不包括 s 自己,一共有 4 个前缀('l', 'le', 'lev', 'leve')和 4 个后缀('l', 'el', 'vel', 'evel')。最长的既是前缀也是后缀的字符串是 'l' 。
- */
-
-function makeNext(str) {
- let index = 1
- let k = 0
- const len = str.length
- const next = Array(len).fill(0)
- for (; index < len; index += 1) {
- while(k > 0 && str[index] !== str[k]) {
- k = next[k - 1]
- }
- if (str[index] === str[k]) {
- k++
- }
- next[index] = k
- }
- return next
-}
-
-// function longestPrefix(s) {
-// const max = s.length
-// const next = makeNext(s)
-// if (max > 0) {
-// return s.slice(0, next[max - 1])
-// }
-// return ''
-// }
-
-console.log(makeNext('leabcdleabcdlv'))
\ No newline at end of file
diff --git "a/\347\256\227\346\263\225/sum-four-divisors.js" "b/\347\256\227\346\263\225/sum-four-divisors.js"
deleted file mode 100644
index 5c4b056..0000000
--- "a/\347\256\227\346\263\225/sum-four-divisors.js"
+++ /dev/null
@@ -1,34 +0,0 @@
-/**
- * @param {number[]} nums
- * @return {number}
- */
-var sumFourDivisors = function(nums) {
- var sum = 0
- for (var i = 0; i < nums.length; i++) {
- var divisorSet = findDivisor(nums[i])
- if (divisorSet.size === 4) {
- divisorSet.forEach(num => {
- sum += num
- })
- }
- }
- return sum
-};
-
-function findDivisor(num) {
- // 超过这个边界就不用继续求值了
- var max = Math.floor(Math.sqrt(num))
- var set = new Set()
- for (var i = 1; i <= max; i ++) {
- var result = num / i
- // 除数是整数
- if (result % 1 === 0) {
- set.add(result)
- // 除以结果 是另一个因数
- set.add(num / result)
- }
- }
- return set
-}
-
-console.log(sumFourDivisors([21,4,7]))
\ No newline at end of file
diff --git "a/\347\256\227\346\263\225/\344\272\214\345\210\206\346\237\245\346\211\276.js" "b/\347\256\227\346\263\225/\344\272\214\345\210\206\346\237\245\346\211\276.js"
deleted file mode 100644
index 19b74e5..0000000
--- "a/\347\256\227\346\263\225/\344\272\214\345\210\206\346\237\245\346\211\276.js"
+++ /dev/null
@@ -1,23 +0,0 @@
-/**
- * 二分搜索 从一个数组中搜索一个确定的数
- */
-
-var search = function(nums, target, offset = 0) {
- let medium = Math.floor(nums.length / 2)
- let mediumVal = nums[medium]
- let left = nums.slice(0, medium)
- let right = nums.slice(medium, nums.length)
-
- if (nums.length === 1 && mediumVal !== target) {
- return -1
- }
-
- if (mediumVal > target) {
- return search(left, target, offset)
- } else if (mediumVal < target) {
- return search(right, target, offset + left.length)
- } else if (mediumVal === target) {
- return medium + offset
- }
-}
-console.log(search([1, 2, 3, 4, 5], 2))
diff --git "a/\347\256\227\346\263\225/\344\272\214\345\217\211\346\240\221.js" "b/\347\256\227\346\263\225/\344\272\214\345\217\211\346\240\221.js"
deleted file mode 100644
index adf1c96..0000000
--- "a/\347\256\227\346\263\225/\344\272\214\345\217\211\346\240\221.js"
+++ /dev/null
@@ -1,9 +0,0 @@
-class TreeNode {
- constructor(val) {
- this.val = val
- this.left = null
- this.right = null
- }
-}
-
-module.exports = TreeNode
\ No newline at end of file
diff --git "a/\347\256\227\346\263\225/\346\227\240\351\207\215\345\244\215\345\255\227\347\254\246\347\232\204\346\234\200\351\225\277\345\255\220\344\270\262\357\274\210\346\273\221\345\212\250\347\252\227\345\217\243\357\274\211.js" "b/\347\256\227\346\263\225/\346\227\240\351\207\215\345\244\215\345\255\227\347\254\246\347\232\204\346\234\200\351\225\277\345\255\220\344\270\262\357\274\210\346\273\221\345\212\250\347\252\227\345\217\243\357\274\211.js"
deleted file mode 100644
index 1a99ef5..0000000
--- "a/\347\256\227\346\263\225/\346\227\240\351\207\215\345\244\215\345\255\227\347\254\246\347\232\204\346\234\200\351\225\277\345\255\220\344\270\262\357\274\210\346\273\221\345\212\250\347\252\227\345\217\243\357\274\211.js"
+++ /dev/null
@@ -1,72 +0,0 @@
-/**
- * 3. 无重复字符的最长子串
- * 给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
-
- 示例 1:
-
- 输入: "abcabcbb"
- 输出: 3
- 解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
- 示例 2:
-
- 输入: "bbbbb"
- 输出: 1
- 解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。
- 示例 3:
-
- 输入: "pwwkew"
- 输出: 3
- 解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
- 请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。
-
- 来源:力扣(LeetCode)
- 链接:https://leetcode-cn.com/problems/longest-substring-without-repeating-characters
- 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
-*/
-var lengthOfLongestSubstring = function(str) {
- if (str.length === 1) {
- return 1
- }
- // 滑动窗口
- var windows = [0, 0]
- var max = 0
-
- for (var i = 0; i < str.length; i++) {
- var char = str[i]
-
- // 当前窗口中的文字
- var windowsStr = str.substring(windows[0], windows[1])
-
- // 窗口中如果已经出现了这个文字 就需要把窗口左侧移动到「上一次出现这个文字」的右边位置
- var windowsCharIdx = windowsStr.indexOf(char)
- if (windowsCharIdx !== -1) {
- // 注意要加上窗口左侧已经移动的距离
- windows[0] += windowsCharIdx + 1
- }
-
- // 右边界始终后移
- windows[1]++
-
- var windowsLength = windows[1] - windows[0]
- if (windowsLength > max) {
- max = windowsLength
- }
- }
-
- return max
-}
-console.log(lengthOfLongestSubstring("abcabcbb"))
-
-/**
- * 参考
- * 什么是「滑动窗口算法」(sliding window algorithm),有哪些应用场景? - 程序员吴师兄的回答 - 知乎
- https://www.zhihu.com/question/314669016/answer/663930108
-
- 注意边界情况很坑,比如'pwwkew'这种,在i = 2遇到第二个w的时候,窗口中的文字是pw,
-
- 要把左边界移动到第一个w的右边一位,也就是[2, 2]再继续开始匹配,此时会从第二个w继续向右滑动。
-
- 再比如'abcdbacd'这种,在i = 4遇到第二个b的时候,窗口中是[a, b, c, d],此时也不能只单纯向后移动一位,而是需要后移到第一个b的右边
-
- 也就是[2, 4]再开始匹配, 也就是从[c, d, b] 再继续往后查找最大的子串。
- */
\ No newline at end of file
diff --git "a/\347\256\227\346\263\225/\347\277\273\350\275\254\344\272\214\345\217\211\346\240\221.js" "b/\347\277\273\350\275\254\344\272\214\345\217\211\346\240\221.js"
similarity index 88%
rename from "\347\256\227\346\263\225/\347\277\273\350\275\254\344\272\214\345\217\211\346\240\221.js"
rename to "\347\277\273\350\275\254\344\272\214\345\217\211\346\240\221.js"
index e7ec87f..6a82ea5 100644
--- "a/\347\256\227\346\263\225/\347\277\273\350\275\254\344\272\214\345\217\211\346\240\221.js"
+++ "b/\347\277\273\350\275\254\344\272\214\345\217\211\346\240\221.js"
@@ -27,8 +27,8 @@
* @param {*} root
* 遍历法,先循环找出所有需要翻转的treeNode,然后遍历翻转即可
*/
-var invertTree = function(root) {
- var queue = [];
+let invertTree = function(root) {
+ let queue = [];
function traverse(tree) {
if (!tree) return;
queue.push(tree);
@@ -38,8 +38,8 @@ var invertTree = function(root) {
traverse(root);
while (queue.length) {
- var node = queue.pop();
- var temp = node.right;
+ let node = queue.pop();
+ let temp = node.right;
node.right = node.left;
node.left = temp;
}
diff --git "a/\350\264\252\345\277\203\347\256\227\346\263\225/\345\210\206\345\217\221\351\245\274\345\271\262-455.js" "b/\350\264\252\345\277\203\347\256\227\346\263\225/\345\210\206\345\217\221\351\245\274\345\271\262-455.js"
new file mode 100644
index 0000000..8af19cb
--- /dev/null
+++ "b/\350\264\252\345\277\203\347\256\227\346\263\225/\345\210\206\345\217\221\351\245\274\345\271\262-455.js"
@@ -0,0 +1,28 @@
+/**
+ * @param {number[]} g
+ * @param {number[]} s
+ * @return {number}
+ */
+let findContentChildren = function (g, s) {
+ g.sort((a, b) => a - b)
+ s.sort((a, b) => a - b)
+
+ let i = 0
+ let j = 0
+
+ let count = 0
+ while (j < s.length && i < g.length) {
+ let need = g[i]
+ let cookie = s[j]
+
+ if (cookie >= need) {
+ count++
+ i++
+ j++
+ } else {
+ j++
+ }
+ }
+
+ return count
+}
diff --git "a/\350\264\252\345\277\203\347\256\227\346\263\225/\345\210\244\346\226\255\345\255\220\345\272\217\345\210\227-392.js" "b/\350\264\252\345\277\203\347\256\227\346\263\225/\345\210\244\346\226\255\345\255\220\345\272\217\345\210\227-392.js"
new file mode 100644
index 0000000..bf9f8f1
--- /dev/null
+++ "b/\350\264\252\345\277\203\347\256\227\346\263\225/\345\210\244\346\226\255\345\255\220\345\272\217\345\210\227-392.js"
@@ -0,0 +1,50 @@
+/**
+ * @param {string} s
+ * @param {string} t
+ * @return {boolean}
+ */
+let isSubsequence = function (s, t) {
+ let i = 0
+ let sl = s.length
+ if (!sl) {
+ return true
+ }
+
+ for (let j = 0; j < t.length; j++) {
+ let target = s[i]
+ let cur = t[j]
+ if (cur === target) {
+ i++
+ if (i === sl) {
+ return true
+ }
+ }
+ }
+
+ return false
+}
+/**
+ * @param {string} s
+ * @param {string} t
+ * @return {boolean}
+ */
+let isSubsequence = function (s, t) {
+ let sl = s.length
+ if (!sl) {
+ return true
+ }
+
+ let i = 0
+ for (let j = 0; j < t.length; j++) {
+ let target = s[i]
+ let cur = t[j]
+ if (cur === target) {
+ i++
+ if (i === sl) {
+ return true
+ }
+ }
+ }
+
+ return false
+}
diff --git "a/\351\200\222\345\275\222\344\270\216\345\233\236\346\272\257/N \347\232\207\345\220\216-51.js" "b/\351\200\222\345\275\222\344\270\216\345\233\236\346\272\257/N \347\232\207\345\220\216-51.js"
new file mode 100644
index 0000000..f3d623b
--- /dev/null
+++ "b/\351\200\222\345\275\222\344\270\216\345\233\236\346\272\257/N \347\232\207\345\220\216-51.js"
@@ -0,0 +1,70 @@
+/**
+ * @param {number} n
+ * @return {string[][]}
+ */
+let solveNQueens = function (n) {
+ let res = []
+
+ // 已摆放皇后的的列下标
+ let columns = []
+ // 已摆放皇后的对角线1下标 左下 -> 右上
+ // 计算某个坐标是否在这个对角线的方式是「行下标 + 列下标」是否相等
+ let dia1 = []
+ // 已摆放皇后的对角线2下标 左上 -> 右下
+ // 计算某个坐标是否在这个对角线的方式是「行下标 - 列下标」是否相等
+ let dia2 = []
+
+ // 尝试在一个n皇后问题中 摆放第index行内的皇后位置
+ let putQueen = (rowIndex, row) => {
+ if (rowIndex === n) {
+ res.push(generateBoard(row))
+ return
+ }
+
+ // 尝试摆第index行的皇后 尝试[0, n-1]列
+ for (let columnIndex = 0; columnIndex < n; columnIndex++) {
+ // 在列上不冲突
+ let columnNotConflict = !columns[columnIndex]
+ // 在对角线1上不冲突
+ let dia1NotConflict = !dia1[rowIndex + columnIndex]
+ // 在对角线2上不冲突
+ let dia2NotConflict = !dia2[rowIndex - columnIndex]
+
+ if (columnNotConflict && dia1NotConflict && dia2NotConflict) {
+
+ columns[columnIndex] = true
+ dia1[rowIndex + columnIndex] = true
+ dia2[rowIndex - columnIndex] = true
+
+ putQueen(rowIndex + 1, row.concat(columnIndex))
+
+ columns[columnIndex] = false
+ dia1[rowIndex + columnIndex] = false
+ dia2[rowIndex - columnIndex] = false
+ }
+ }
+ }
+
+ putQueen(0, [])
+
+ return res
+}
+
+function generateBoard(row) {
+ let n = row.length
+ let res = []
+ for(let y = 0; y < n; y++) {
+ let cur = ''
+ for (let x = 0; x < n; x++) {
+ if (x === row[y]) {
+ cur += 'Q'
+ }else {
+ cur += '.'
+ }
+ }
+ res.push(cur)
+ }
+ return res
+}
+
+console.log(solveNQueens(4))
diff --git "a/\351\200\222\345\275\222\344\270\216\345\233\236\346\272\257/\344\270\215\345\220\214\350\267\257\345\276\204 III-980.js" "b/\351\200\222\345\275\222\344\270\216\345\233\236\346\272\257/\344\270\215\345\220\214\350\267\257\345\276\204 III-980.js"
new file mode 100644
index 0000000..1213047
--- /dev/null
+++ "b/\351\200\222\345\275\222\344\270\216\345\233\236\346\272\257/\344\270\215\345\220\214\350\267\257\345\276\204 III-980.js"
@@ -0,0 +1,72 @@
+/**
+ * @param {number[][]} grid
+ * @return {number}
+ */
+let uniquePathsIII = function (grid) {
+ let maxY = grid.length
+ if (!maxY) return 0
+ let maxX = grid[0].length
+
+ let validCellsCount = 0
+ let entry
+ let visited = []
+ for (let y = 0; y < maxY; y++) {
+ visited[y] = []
+ for (let x = 0; x < maxX; x++) {
+ let val = grid[y][x]
+ if (val === 0) {
+ validCellsCount++
+ }
+ if (val === 1) {
+ entry = [y, x]
+ }
+ }
+ }
+
+ let isValid = (y, x) => {
+ return (
+ y >= 0 &&
+ y < maxY &&
+ x >= 0 &&
+ x < maxX &&
+ !visited[y][x] &&
+ grid[y][x] !== -1
+ )
+ }
+
+ let dirs = [
+ [-1, 0],
+ [1, 0],
+ [0, -1],
+ [0, 1],
+ ]
+ let res = 0
+
+ let dfs = (y, x, passCount) => {
+ let val = grid[y][x]
+ if (val === 2) {
+ if (passCount === validCellsCount) {
+ res++
+ }
+ return
+ } else if (val === 0) {
+ passCount += 1
+ }
+
+ for (let [diffY, diffX] of dirs) {
+ let nextY = y + diffY
+ let nextX = x + diffX
+ if (isValid(nextY, nextX)) {
+ visited[nextY][nextX] = true
+ dfs(nextY, nextX, passCount)
+ visited[nextY][nextX] = false
+ }
+ }
+ }
+
+ let [entryY, entryX] = entry
+ visited[entryY][entryX] = true
+ dfs(entryY, entryX, 0)
+
+ return res
+}
diff --git "a/\351\200\222\345\275\222\344\270\216\345\233\236\346\272\257/\344\272\214\350\277\233\345\210\266\346\211\213\350\241\250-401.js" "b/\351\200\222\345\275\222\344\270\216\345\233\236\346\272\257/\344\272\214\350\277\233\345\210\266\346\211\213\350\241\250-401.js"
new file mode 100644
index 0000000..0a9ce85
--- /dev/null
+++ "b/\351\200\222\345\275\222\344\270\216\345\233\236\346\272\257/\344\272\214\350\277\233\345\210\266\346\211\213\350\241\250-401.js"
@@ -0,0 +1,54 @@
+/**
+ * @param {number} num
+ * @return {string[]}
+ */
+let HOURS = [1, 2, 4, 8]
+let MINUTES = [1, 2, 4, 8, 16, 32]
+
+let readBinaryWatch = function (num) {
+ let res = []
+
+ let combine = (arr, num) => {
+ if (num === 0) {
+ return [0]
+ }
+ let res = []
+ let helper = (start, prevCount, prevSum) => {
+ if (prevCount === num) {
+ res.push(prevSum)
+ return
+ }
+
+ for (let i = start; i < arr.length; i++) {
+ let cur = arr[i]
+ helper(i + 1, prevCount + 1, prevSum + cur)
+ }
+ }
+ helper(0, 0, 0)
+ return res
+ }
+
+ for (let i = 0; i <= num; i++) {
+ let hours = combine(HOURS, i)
+ let minutes = combine(MINUTES, num - i)
+
+ for (let hour of hours) {
+ if (hour > 11) continue
+ for (let minute of minutes) {
+ if (minute > 59) {
+ continue
+ }
+ res.push(`${hour}:${padLeft(minute)}`)
+ }
+ }
+ }
+ return res
+}
+
+function padLeft(num) {
+ let str = num.toString()
+ if (str.length === 1) {
+ str = `0${str}`
+ }
+ return str
+}
\ No newline at end of file
diff --git "a/\351\200\222\345\275\222\344\270\216\345\233\236\346\272\257/\345\205\250\346\216\222\345\210\227 II-47.js" "b/\351\200\222\345\275\222\344\270\216\345\233\236\346\272\257/\345\205\250\346\216\222\345\210\227 II-47.js"
new file mode 100644
index 0000000..96278c2
--- /dev/null
+++ "b/\351\200\222\345\275\222\344\270\216\345\233\236\346\272\257/\345\205\250\346\216\222\345\210\227 II-47.js"
@@ -0,0 +1,39 @@
+
+let uniqSymbol = 'X'
+
+let permuteUnique = function (nums) {
+ let n = nums.length
+ if (n === 1) {
+ return [nums]
+ }
+ let permuteSet = (nums) => {
+ let n = nums.length
+ if (n === 0) {
+ return new Set()
+ }
+ if (n === 1) {
+ return new Set(nums)
+ }
+
+ let res = new Set()
+ for (let i = 0; i < n; i++) {
+ let use = nums[i]
+ if (use === undefined) {
+ continue
+ }
+ let rest = nums.slice(0, i).concat(nums.slice(i + 1, n))
+ let restPermuteds = permuteSet(rest)
+ restPermuteds.forEach((restPermuted) => {
+ res.add(`${use}${uniqSymbol}${restPermuted}`)
+ })
+ }
+
+ return res
+ }
+
+ let permuted = permuteSet(nums)
+
+ return Array.from(permuted).map((val) => val.split(uniqSymbol).map(Number))
+}
+
+console.log(permuteUnique([-1,2,-1,2,1,-1,2,1]))
diff --git "a/\351\200\222\345\275\222\344\270\216\345\233\236\346\272\257/\345\205\250\346\216\222\345\210\227-46.js" "b/\351\200\222\345\275\222\344\270\216\345\233\236\346\272\257/\345\205\250\346\216\222\345\210\227-46.js"
new file mode 100644
index 0000000..59bc751
--- /dev/null
+++ "b/\351\200\222\345\275\222\344\270\216\345\233\236\346\272\257/\345\205\250\346\216\222\345\210\227-46.js"
@@ -0,0 +1,24 @@
+/**
+ * @param {number[]} nums
+ * @return {number[][]}
+ */
+let permute = function (nums) {
+ let n = nums.length
+ if (n === 1) {
+ return [nums]
+ }
+
+ let res = []
+ for (let i = 0; i < n; i++) {
+ let use = nums[i]
+ let rest = nums.slice(0, i).concat(nums.slice(i + 1, n))
+ let restPermuteds = permute(rest)
+ for (let restPermuted of restPermuteds) {
+ res.push(restPermuted.concat(use))
+ }
+ }
+
+ return res
+}
+
+console.log(permute([1, 2, 3]))
diff --git "a/\351\200\222\345\275\222\344\270\216\345\233\236\346\272\257/\345\210\206\345\211\262\345\233\236\346\226\207\344\270\262-131.js" "b/\351\200\222\345\275\222\344\270\216\345\233\236\346\272\257/\345\210\206\345\211\262\345\233\236\346\226\207\344\270\262-131.js"
new file mode 100644
index 0000000..c973e26
--- /dev/null
+++ "b/\351\200\222\345\275\222\344\270\216\345\233\236\346\272\257/\345\210\206\345\211\262\345\233\236\346\226\207\344\270\262-131.js"
@@ -0,0 +1,51 @@
+/**
+ * @param {string} s
+ * @return {string[][]}
+ */
+
+let partition = function (s) {
+ let n = s.length
+ let ret = []
+ let find = function (start, prev) {
+ // 最少分割一个字符 最多分割到末尾前一位
+ for (let i = 1; i <= n; i++) {
+ let end = start + i
+ let cur = s.substring(start, end)
+ if (cur) {
+ let res = prev.concat(cur)
+ if (isPalindrome(cur)) {
+ if (end === n) {
+ ret.push(res)
+ } else {
+ find(start + i, res)
+ }
+ }
+ }
+ }
+ }
+ find(0, [])
+ return ret
+}
+
+function isPalindrome(s) {
+ if (!s) {
+ return false
+ }
+ let i = 0
+ let j = s.length - 1
+
+ while (i < j) {
+ let head = s[i]
+ let tail = s[j]
+
+ if (head !== tail) {
+ return false
+ } else {
+ i++
+ j--
+ }
+ }
+ return true
+}
+
+console.log(partition("aab"))
diff --git "a/\351\200\222\345\275\222\344\270\216\345\233\236\346\272\257/\345\215\225\350\257\215\346\220\234\347\264\242 II-212.Trie\347\211\210\346\234\254.js" "b/\351\200\222\345\275\222\344\270\216\345\233\236\346\272\257/\345\215\225\350\257\215\346\220\234\347\264\242 II-212.Trie\347\211\210\346\234\254.js"
new file mode 100644
index 0000000..9032686
--- /dev/null
+++ "b/\351\200\222\345\275\222\344\270\216\345\233\236\346\272\257/\345\215\225\350\257\215\346\220\234\347\264\242 II-212.Trie\347\211\210\346\234\254.js"
@@ -0,0 +1,112 @@
+/**
+ * Initialize your data structure here.
+ */
+var Trie = function () {
+ this.root = new TrieNode()
+}
+
+var TrieNode = function () {
+ this.children = new Map()
+ this.isEnd = false
+}
+
+/**
+ * Inserts a word into the trie.
+ * @param {string} word
+ * @return {void}
+ */
+Trie.prototype.insert = function (word) {
+ let node = this.root
+
+ for (let i = 0; i < word.length; i++) {
+ let { children } = node
+ let trieNode = children.get(word[i])
+ if (!trieNode) {
+ trieNode = new TrieNode()
+ children.set(word[i], trieNode)
+ }
+ node = trieNode
+
+ if (i === word.length - 1) {
+ node.isEnd = true
+ node.word = word
+ }
+ }
+}
+
+let dirs = [
+ [0, 1],
+ [0, -1],
+ [-1, 0],
+ [1, 0],
+]
+/**
+ * @param {character[][]} board
+ * @param {string[]} words
+ * @return {string[]}
+ */
+let findWords = function (board, words) {
+ let maxY = board.length
+ if (!maxY) return []
+ let maxX = board[0].length
+
+ let rootTrie = new Trie()
+ for (let word of words) {
+ rootTrie.insert(word)
+ }
+
+ // 记录已访问过的二维下标
+ let visited = []
+ for (let y = 0; y < maxY; y++) {
+ visited[y] = []
+ }
+
+ let isValid = (x, y) => {
+ return x >= 0 && x < maxX && y >= 0 && y < maxY && !visited[y][x]
+ }
+
+ // 返回结果
+ let res = []
+
+ let dfs = (x, y, trie) => {
+ let char = board[y][x]
+ let children = trie.children
+ let nextTrie = children && children.get(char)
+ if (nextTrie) {
+ if (nextTrie.word) {
+ res.push(nextTrie.word)
+ nextTrie.word = null
+ } else {
+ visited[y][x] = true
+ for (let dir of dirs) {
+ let [offsetY, offsetX] = dir
+ let nextY = y + offsetY
+ let nextX = x + offsetX
+ if (isValid(nextX, nextY)) {
+ dfs(nextX, nextY, nextTrie)
+ }
+ }
+ visited[y][x] = false
+ }
+ }
+ }
+
+ for (let y = 0; y < maxY; y++) {
+ for (let x = 0; x < maxX; x++) {
+ if (y === 1 && x === 0) debugger
+ dfs(x, y, rootTrie.root)
+ }
+ }
+
+ return Array.from(new Set(res))
+}
+
+console.log(
+ findWords(
+ [
+ ["a", "b"],
+ ["a", "a"],
+ ],
+ ["aaba"]
+ )
+)
diff --git "a/\351\200\222\345\275\222\344\270\216\345\233\236\346\272\257/\345\215\225\350\257\215\346\220\234\347\264\242 II-212.js" "b/\351\200\222\345\275\222\344\270\216\345\233\236\346\272\257/\345\215\225\350\257\215\346\220\234\347\264\242 II-212.js"
new file mode 100644
index 0000000..66d2f3d
--- /dev/null
+++ "b/\351\200\222\345\275\222\344\270\216\345\233\236\346\272\257/\345\215\225\350\257\215\346\220\234\347\264\242 II-212.js"
@@ -0,0 +1,87 @@
+let dirs = [
+ [0, 1],
+ [0, -1],
+ [-1, 0],
+ [1, 0],
+]
+/**
+ * @param {character[][]} board
+ * @param {string[]} words
+ * @return {string[]}
+ */
+let findWords = function (board, words) {
+ let maxY = board.length
+ if (!maxY) return []
+ let maxX = board[0].length
+
+ // 记录已访问过的二维下标
+ let visited = []
+ for (let y = 0; y < maxY; y++) {
+ visited[y] = []
+ }
+
+ let isValid = (x, y) => {
+ return x >= 0 && x < maxX && y >= 0 && y < maxY && !visited[y][x]
+ }
+
+ // 返回结果
+ let res = []
+
+ let dfs = (x, y, word, index) => {
+ let char = board[y][x]
+ let targetChar = word[index]
+ if (char === targetChar) {
+ if (index === word.length - 1) {
+ res.push(word)
+ } else {
+ visited[y][x] = true
+ for (let dir of dirs) {
+ let [offsetY, offsetX] = dir
+ let nextY = y + offsetY
+ let nextX = x + offsetX
+ if (isValid(nextX, nextY)) {
+ dfs(nextX, nextY, word, index + 1)
+ }
+ }
+ visited[y][x] = false
+ }
+ }
+ }
+
+ let prefixMap = new Map()
+ for (let y = 0; y < maxY; y++) {
+ for (let x = 0; x < maxX; x++) {
+ let prefix = board[y][x]
+ let pos = prefixMap.get(prefix)
+ if (!pos) {
+ prefixMap.set(prefix, [[y, x]])
+ } else {
+ prefixMap.set(prefix, [...pos, [y, x]])
+ }
+ }
+ }
+
+ let find = (word) => {
+ let head = word[0]
+ let pos = prefixMap.get(head)
+ if (pos) {
+ pos.forEach(([y, x]) => {
+ dfs(x, y, word, 0)
+ })
+ }
+ }
+
+ words.forEach(find)
+
+ return Array.from(new Set(res))
+}
+
+console.log(
+ findWords(
+ [
+ ["a", "b"],
+ ["a", "a"],
+ ],
+ ["aba", "baa", "bab", "aaab", "aaa", "aaaa", "aaba"]
+ )
+)
diff --git "a/\351\200\222\345\275\222\344\270\216\345\233\236\346\272\257/\345\215\225\350\257\215\346\220\234\347\264\242-79.js" "b/\351\200\222\345\275\222\344\270\216\345\233\236\346\272\257/\345\215\225\350\257\215\346\220\234\347\264\242-79.js"
new file mode 100644
index 0000000..c9306df
--- /dev/null
+++ "b/\351\200\222\345\275\222\344\270\216\345\233\236\346\272\257/\345\215\225\350\257\215\346\220\234\347\264\242-79.js"
@@ -0,0 +1,64 @@
+/**
+ * @param {character[][]} board
+ * @param {string} word
+ * @return {boolean}
+ */
+let directions = [[-1, 0], [1, 0], [0, -1], [0, 1]] // 左 右 上 下
+
+let exist = function (board, word) {
+ let maxY = board.length
+ if (!maxY) return false
+ let maxX = board[0].length
+
+ // 二维数组记录已访问过的元素
+ let visited = new Array(maxY)
+ for (let y = 0; y < visited.length; y++) {
+ visited[y] = new Array(maxX)
+ }
+
+ let inArea = (x, y) => {
+ return x >= 0 && x < maxX && y >= 0 && y < maxY
+ }
+
+ let search = (startX, startY, wordIndex) => {
+ // 当前起始字符不匹配 直接失败
+ let curCell = board[startY][startX]
+ let curChar = word[wordIndex]
+ if (curCell !== curChar) {
+ return false
+ }
+
+ // 如果递归到最后一位字符 就直接返回最后一位字符是否匹配成功
+ if (wordIndex === word.length - 1) {
+ return curChar === curChar
+ }
+
+ // 进一步递归 先记录为已访问元素 防止递归的时候重复访问
+ visited[startY][startX] = true
+
+ for (let direction of directions) {
+ let [x, y] = direction
+ let nextX = startX + x
+ let nextY = startY + y
+
+ // 需要保证未越界且未被访问过
+ if (inArea(nextX, nextY) && !visited[nextY][nextX]) {
+ if (search(nextX, nextY, wordIndex + 1)) {
+ return true
+ }
+ }
+ }
+ // 重置已访问标记位
+ visited[startY][startX] = false
+ }
+
+ for (let y = 0; y < maxY; y++) {
+ for (let x = 0; x < maxX; x++) {
+ if (search(x, y, 0)) {
+ return true
+ }
+ }
+ }
+
+ return false
+};
\ No newline at end of file
diff --git "a/\351\200\222\345\275\222\344\270\216\345\233\236\346\272\257/\345\222\214\344\270\272K\347\232\204\345\255\220\346\225\260\347\273\204-560.js" "b/\351\200\222\345\275\222\344\270\216\345\233\236\346\272\257/\345\222\214\344\270\272K\347\232\204\345\255\220\346\225\260\347\273\204-560.js"
new file mode 100644
index 0000000..25582b5
--- /dev/null
+++ "b/\351\200\222\345\275\222\344\270\216\345\233\236\346\272\257/\345\222\214\344\270\272K\347\232\204\345\255\220\346\225\260\347\273\204-560.js"
@@ -0,0 +1,23 @@
+/**
+ * @param {number[]} nums
+ * @param {number} k
+ * @return {number}
+ */
+let subarraySum = function (nums, k) {
+ let n = nums.length
+ if (!n) {
+ return 0
+ }
+
+ let res = 0
+ for (let i = 0; i < n; i++) {
+ let total = 0
+ for (let j = i; j < n; j++) {
+ total += nums[j]
+ if (total === k) {
+ res += 1
+ }
+ }
+ }
+ return res
+};
\ No newline at end of file
diff --git "a/\351\200\222\345\275\222\344\270\216\345\233\236\346\272\257/\345\244\215\345\216\237ip\345\234\260\345\235\200-93.js" "b/\351\200\222\345\275\222\344\270\216\345\233\236\346\272\257/\345\244\215\345\216\237ip\345\234\260\345\235\200-93.js"
new file mode 100644
index 0000000..c1ffaa6
--- /dev/null
+++ "b/\351\200\222\345\275\222\344\270\216\345\233\236\346\272\257/\345\244\215\345\216\237ip\345\234\260\345\235\200-93.js"
@@ -0,0 +1,43 @@
+/**
+ * @param {string} s
+ * @return {string[]}
+ */
+let restoreIpAddresses = function (s) {
+ let res = []
+ let findPos = (start, prev, used) => {
+ if (used === 3) {
+ let rest = s.substr(start)
+ // 点全部用光后 剩余字符依然是一个合格的ip chunk
+ // 就视为一个答案 放入数组
+ if (isValidChunk(rest)) {
+ res.push(prev.concat(rest).join("."))
+ }
+ return
+ }
+
+ for (let i = 1; i <= 3; i++) {
+ let end = start + i
+ let cur = s.substring(start, end)
+ if (isValidChunk(cur)) {
+ findPos(end, prev.concat(cur), used + 1)
+ }
+ }
+ }
+
+ findPos(0, [], 0)
+
+ return res
+}
+
+function isValidChunk(str) {
+ let strLen = str.length
+ if (strLen === 0) {
+ return false
+ }
+ // 开头是0的话 只能整个字符串只有一位0才行
+ if (str[0] === "0") {
+ return strLen === 1
+ }
+ let num = Number(str)
+ return num <= 255
+}
diff --git "a/\351\200\222\345\275\222\344\270\216\345\233\236\346\272\257/\345\255\220\351\233\206 II-90.js" "b/\351\200\222\345\275\222\344\270\216\345\233\236\346\272\257/\345\255\220\351\233\206 II-90.js"
new file mode 100644
index 0000000..d5eb09e
--- /dev/null
+++ "b/\351\200\222\345\275\222\344\270\216\345\233\236\346\272\257/\345\255\220\351\233\206 II-90.js"
@@ -0,0 +1,45 @@
+/**
+ * @param {number[]} nums
+ * @return {number[][]}
+ */
+var subsetsWithDup = function (nums) {
+ let n = nums.length
+ let res = []
+ if (!n) {
+ return res
+ }
+
+ nums.sort()
+
+ let used = {}
+
+ let helper = (start, prev, target) => {
+ if (prev.length === target) {
+ let key = genKey(prev)
+ if (!used[key]) {
+ res.push(prev)
+ used[key] = true
+ }
+ return
+ }
+
+ for (let i = start; i < n; i++) {
+ let rest = n - i
+ let need = target - prev.length
+ if (rest < need) {
+ continue
+ }
+ helper(i + 1, prev.concat(nums[i]), target)
+ }
+ }
+
+ for (let i = 1; i <= n; i++) {
+ helper(0, [], i)
+ }
+
+ return [[], ...res]
+};
+
+function genKey(arr) {
+ return arr.join('~')
+}
\ No newline at end of file
diff --git "a/\351\200\222\345\275\222\344\270\216\345\233\236\346\272\257/\345\255\220\351\233\206-78.js" "b/\351\200\222\345\275\222\344\270\216\345\233\236\346\272\257/\345\255\220\351\233\206-78.js"
new file mode 100644
index 0000000..ca951d4
--- /dev/null
+++ "b/\351\200\222\345\275\222\344\270\216\345\233\236\346\272\257/\345\255\220\351\233\206-78.js"
@@ -0,0 +1,32 @@
+/**
+ * @param {number[]} nums
+ * @return {number[][]}
+ */
+let subsets = function (nums) {
+ let res = []
+ let n = nums.length
+ if (n === 0) {
+ return res
+ }
+
+ let helper = (start, prev, targetLength) => {
+ if (start > n) {
+ return
+ }
+ if (prev.length === targetLength) {
+ res.push(prev)
+ return
+ }
+
+ for (let i = start; i < n; i++) {
+ let cur = nums[i]
+ helper(i + 1, prev.concat(cur), targetLength)
+ }
+ }
+
+ for (let j = 1; j <= nums.length; j++) {
+ helper(0, [], j)
+ }
+
+ return [[], ...res]
+}
diff --git "a/\351\200\222\345\275\222\344\270\216\345\233\236\346\272\257/\345\255\227\346\257\215\345\244\247\345\260\217\345\206\231\345\205\250\346\216\222\345\210\227-784.js" "b/\351\200\222\345\275\222\344\270\216\345\233\236\346\272\257/\345\255\227\346\257\215\345\244\247\345\260\217\345\206\231\345\205\250\346\216\222\345\210\227-784.js"
new file mode 100644
index 0000000..91ba7b7
--- /dev/null
+++ "b/\351\200\222\345\275\222\344\270\216\345\233\236\346\272\257/\345\255\227\346\257\215\345\244\247\345\260\217\345\206\231\345\205\250\346\216\222\345\210\227-784.js"
@@ -0,0 +1,34 @@
+/**
+ * @param {string} S
+ * @return {string[]}
+ */
+let letterCasePermutation = function (S) {
+ let res = []
+
+ let helper = (prev, rest) => {
+ if (prev.length === S.length) {
+ res.push(prev)
+ return
+ }
+
+ let char = rest[0]
+ let word1 = prev + char
+ let nextRest = rest.substring(1)
+
+ if (!isNaN(Number(char))) {
+ helper(word1, nextRest)
+ return
+ } else {
+ let upperChar = char.toUpperCase()
+ let char2 = upperChar === char ? char.toLowerCase() : upperChar
+ let word2 = prev + char2
+
+ helper(word1, nextRest)
+ helper(word2, nextRest)
+ }
+ }
+
+ helper('', S)
+
+ return res
+};
\ No newline at end of file
diff --git "a/\351\200\222\345\275\222\344\270\216\345\233\236\346\272\257/\345\255\227\346\257\215\350\277\255\344\273\243\347\273\204\345\220\210\345\231\250-1286.js" "b/\351\200\222\345\275\222\344\270\216\345\233\236\346\272\257/\345\255\227\346\257\215\350\277\255\344\273\243\347\273\204\345\220\210\345\231\250-1286.js"
new file mode 100644
index 0000000..709bae1
--- /dev/null
+++ "b/\351\200\222\345\275\222\344\270\216\345\233\236\346\272\257/\345\255\227\346\257\215\350\277\255\344\273\243\347\273\204\345\220\210\345\231\250-1286.js"
@@ -0,0 +1,52 @@
+/**
+ * @param {string} characters
+ * @param {number} combinationLength
+ */
+let CombinationIterator = function (characters, combinationLength) {
+ let cl = characters.length
+ let res = []
+ let helper = (start, prev) => {
+ let pl = prev.length
+ for (let i = start; i < cl; i++) {
+ let rest = cl - i
+ let diff = combinationLength - pl
+ if (diff > rest) {
+ return
+ }
+ let next = prev + characters[i]
+ if (next.length == combinationLength) {
+ res.push(next)
+ } else {
+ helper(i + 1, next)
+ }
+ }
+ }
+ helper(0, "")
+ this.res = res.sort((a, b) => (a > b ? 1 : -1))
+ this.point = 0
+}
+
+/**
+ * @return {string}
+ */
+CombinationIterator.prototype.next = function () {
+ if (!this.hasNext()) {
+ return undefined
+ }
+ let val = this.res[this.point++]
+ return val
+}
+
+/**
+ * @return {boolean}
+ */
+CombinationIterator.prototype.hasNext = function () {
+ return this.point !== this.res.length
+}
+
+/**
+ * Your CombinationIterator object will be instantiated and called as such:
+ * var obj = new CombinationIterator(characters, combinationLength)
+ * var param_1 = obj.next()
+ * var param_2 = obj.hasNext()
+ */
diff --git "a/\351\200\222\345\275\222\344\270\216\345\233\236\346\272\257/\346\213\254\345\217\267-\351\235\242\350\257\225\351\242\230 08.09.js" "b/\351\200\222\345\275\222\344\270\216\345\233\236\346\272\257/\346\213\254\345\217\267-\351\235\242\350\257\225\351\242\230 08.09.js"
new file mode 100644
index 0000000..604f5c4
--- /dev/null
+++ "b/\351\200\222\345\275\222\344\270\216\345\233\236\346\272\257/\346\213\254\345\217\267-\351\235\242\350\257\225\351\242\230 08.09.js"
@@ -0,0 +1,23 @@
+/**
+ * @param {number} n
+ * @return {string[]}
+ */
+let generateParenthesis = function (n) {
+ let res = []
+
+ let helper = (left, right, prev) => {
+ if (left < 0 || right < 0 || right < left) {
+ return
+ }
+ if (left === 0 && right === 0) {
+ res.push(prev)
+ return
+ }
+
+ helper(left - 1, right, prev + "(")
+ helper(left, right - 1, prev + ")")
+ }
+
+ helper(n, n, '')
+ return res
+};
\ No newline at end of file
diff --git "a/\351\200\222\345\275\222\344\270\216\345\233\236\346\272\257/\346\264\273\345\255\227\345\215\260\345\210\267-1079.js" "b/\351\200\222\345\275\222\344\270\216\345\233\236\346\272\257/\346\264\273\345\255\227\345\215\260\345\210\267-1079.js"
new file mode 100644
index 0000000..40ff332
--- /dev/null
+++ "b/\351\200\222\345\275\222\344\270\216\345\233\236\346\272\257/\346\264\273\345\255\227\345\215\260\345\210\267-1079.js"
@@ -0,0 +1,23 @@
+/**
+ * @param {string} tiles
+ * @return {number}
+ */
+let numTilePossibilities = function (tiles) {
+ let res = new Set()
+
+ let helper = (prev, rest) => {
+ if (prev.length > 0) {
+ res.add(prev)
+ }
+
+ for (let i = 0; i < rest.length; i++) {
+ let char = rest[i]
+ let cur = prev + char
+ helper(cur, rest.substring(0, i) + rest.substring(i + 1))
+ }
+ }
+
+ helper('', tiles)
+
+ return res.size
+};
\ No newline at end of file
diff --git "a/\351\200\222\345\275\222\344\270\216\345\233\236\346\272\257/\347\224\265\350\257\235\345\217\267\347\240\201\347\232\204\345\255\227\346\257\215\347\273\204\345\220\210-17.js" "b/\351\200\222\345\275\222\344\270\216\345\233\236\346\272\257/\347\224\265\350\257\235\345\217\267\347\240\201\347\232\204\345\255\227\346\257\215\347\273\204\345\220\210-17.js"
new file mode 100644
index 0000000..57bda1a
--- /dev/null
+++ "b/\351\200\222\345\275\222\344\270\216\345\233\236\346\272\257/\347\224\265\350\257\235\345\217\267\347\240\201\347\232\204\345\255\227\346\257\215\347\273\204\345\220\210-17.js"
@@ -0,0 +1,48 @@
+/**
+ * @param {string} digits
+ * @return {string[]}
+ */
+let letterMap = [
+ " ", //0
+ "", //1
+ "abc", //2
+ "def", //3
+ "ghi", //4
+ "jkl", //5
+ "mno", //6
+ "pqrs", //7
+ "tuv", //8
+ "wxyz", //9
+]
+
+let letterCombinations = function (digits) {
+ let res = []
+
+ if (digits === "") {
+ return res
+ }
+
+ /**
+ *
+ * @param {number} index 当前处理到的下标位置
+ * @param {string} str 当前已经凑成的字符串
+ */
+ let findCombinations = (index, str) => {
+ if (digits.length === index) {
+ res.push(str)
+ return
+ }
+
+ let char = digits[index] // 数字
+ let letters = letterMap[Number(char)] // 数字对应的字母
+
+ for (let i = 0; i < letters.length; i++) {
+ let letter = letters[i]
+ findCombinations(index + 1, `${str}${letter}`)
+ }
+ }
+
+ findCombinations(0, "")
+
+ return res
+}
diff --git "a/\351\200\222\345\275\222\344\270\216\345\233\236\346\272\257/\347\237\251\351\230\265\347\275\256\351\233\266-73.js" "b/\351\200\222\345\275\222\344\270\216\345\233\236\346\272\257/\347\237\251\351\230\265\347\275\256\351\233\266-73.js"
new file mode 100644
index 0000000..fff9854
--- /dev/null
+++ "b/\351\200\222\345\275\222\344\270\216\345\233\236\346\272\257/\347\237\251\351\230\265\347\275\256\351\233\266-73.js"
@@ -0,0 +1,37 @@
+/**
+ * @param {number[][]} matrix
+ * @return {void} Do not return anything, modify matrix in-place instead.
+ */
+let setZeroes = function (matrix) {
+ let maxY = matrix.length
+ if (!maxY) return
+ let maxX = matrix[0].length
+
+ let handledRows = []
+ let handledColumns = []
+
+ let zeros = []
+ for (let y = 0; y < maxY; y++) {
+ for (let x = 0; x < maxX; x++) {
+ let val = matrix[y][x]
+ if (val === 0) {
+ zeros.push([y, x])
+ }
+ }
+ }
+
+ for (let [y, x] of zeros) {
+ if (!handledRows[x]) {
+ for (let i = 0; i < maxY; i++) {
+ matrix[i][x] = 0
+ }
+ handledRows[x] = true
+ }
+ if (!handledColumns[y]) {
+ for (let i = 0; i < maxX; i++) {
+ matrix[y][i] = 0
+ }
+ handledColumns[y] = true
+ }
+ }
+};
\ No newline at end of file
diff --git "a/\351\200\222\345\275\222\344\270\216\345\233\236\346\272\257/\347\273\204\345\220\210-77.js" "b/\351\200\222\345\275\222\344\270\216\345\233\236\346\272\257/\347\273\204\345\220\210-77.js"
new file mode 100644
index 0000000..8f3ccf1
--- /dev/null
+++ "b/\351\200\222\345\275\222\344\270\216\345\233\236\346\272\257/\347\273\204\345\220\210-77.js"
@@ -0,0 +1,33 @@
+/**
+ * @param {number} n
+ * @param {number} k
+ * @return {number[][]}
+ */
+let combine = function (n, k) {
+ let ret = []
+
+ let helper = (start, prev) => {
+ let len = prev.length
+ if (len === k) {
+ ret.push(prev)
+ return
+ }
+
+ if (start > n) {
+ return
+ }
+
+ // 还有 rest 个位置待填补
+ let rest = k - prev.length
+ for (let i = start; i <= n; i++) {
+ if (n - i + 1 < rest) {
+ continue
+ }
+ helper(i + 1, prev.concat(i))
+ }
+ }
+ helper(1, [])
+ return ret
+}
+
+console.log(combine(4, 2))
diff --git "a/\351\200\222\345\275\222\344\270\216\345\233\236\346\272\257/\347\273\204\345\220\210\346\200\273\345\222\214-39.js" "b/\351\200\222\345\275\222\344\270\216\345\233\236\346\272\257/\347\273\204\345\220\210\346\200\273\345\222\214-39.js"
new file mode 100644
index 0000000..f55dc03
--- /dev/null
+++ "b/\351\200\222\345\275\222\344\270\216\345\233\236\346\272\257/\347\273\204\345\220\210\346\200\273\345\222\214-39.js"
@@ -0,0 +1,32 @@
+/**
+ * @param {number[]} candidates
+ * @param {number} target
+ * @return {number[][]}
+ */
+let combinationSum = function (candidates, target) {
+ let res = []
+
+ let helper = (start, prevSum, prevArr) => {
+ // 由于全是正整数 所以一旦和大于目标值了 直接结束本次递归即可。
+ if (prevSum > target) {
+ return
+ }
+ // 目标值达成
+ if (prevSum === target) {
+ res.push(prevArr)
+ return
+ }
+
+ for (let i = start; i < candidates.length; i++) {
+ // 这里还是继续从start本身开始 因为多个重复值是允许的
+ let cur = candidates[i]
+ let sum = prevSum + cur
+ let arr = prevArr.concat(cur)
+ helper(i, sum, arr)
+ }
+ }
+
+ helper(0, 0, [])
+
+ return res
+}
\ No newline at end of file
diff --git "a/\351\200\222\345\275\222\344\270\216\345\233\236\346\272\257/\347\273\204\345\220\210\346\200\273\345\222\214-40.js" "b/\351\200\222\345\275\222\344\270\216\345\233\236\346\272\257/\347\273\204\345\220\210\346\200\273\345\222\214-40.js"
new file mode 100644
index 0000000..84a3750
--- /dev/null
+++ "b/\351\200\222\345\275\222\344\270\216\345\233\236\346\272\257/\347\273\204\345\220\210\346\200\273\345\222\214-40.js"
@@ -0,0 +1,47 @@
+let genKey = (arr) => arr.join("~")
+/**
+ * @param {number[]} candidates
+ * @param {number} target
+ * @return {number[][]}
+ */
+let combinationSum2 = function (candidates, target) {
+ let res = []
+
+ if (!candidates.length) {
+ return res
+ }
+
+ candidates.sort()
+
+ let used = {}
+
+ let helper = (start, prevSum, prevArr) => {
+ // 由于全是正整数 所以一旦和大于目标值了 直接结束本次递归即可。
+ if (prevSum > target) {
+ return
+ }
+ // 目标值达成
+ if (prevSum === target) {
+ let key = genKey(prevArr)
+ if (!used[key]) {
+ res.push(prevArr)
+ used[key] = true
+ }
+ return
+ }
+
+ for (let i = start; i < candidates.length; i++) {
+ // 这里还是继续从start本身开始 因为多个重复值是允许的
+ let cur = candidates[i]
+ let sum = prevSum + cur
+ let arr = prevArr.concat(cur)
+ helper(i + 1, sum, arr)
+ }
+ }
+
+ helper(0, 0, [])
+
+ return res
+}
+
+console.log(combinationSum2([2, 1, 2, 1, 3], 6))
diff --git "a/\351\200\222\345\275\222\344\270\216\345\233\236\346\272\257/\350\236\272\346\227\213\347\237\251\351\230\265-54.js" "b/\351\200\222\345\275\222\344\270\216\345\233\236\346\272\257/\350\236\272\346\227\213\347\237\251\351\230\265-54.js"
new file mode 100644
index 0000000..5b64a29
--- /dev/null
+++ "b/\351\200\222\345\275\222\344\270\216\345\233\236\346\272\257/\350\236\272\346\227\213\347\237\251\351\230\265-54.js"
@@ -0,0 +1,56 @@
+/**
+ * @param {number[][]} matrix
+ * @return {number[]}
+ */
+let spiralOrder = function (matrix) {
+ let maxY = matrix.length
+ if (!maxY) return []
+ let maxX = matrix[0].length
+
+ // 记录一个 visited 数组
+ // 按照 右 -> 下 -> 左 -> 上 的方向不断前进
+ // 直到遇到边界或者已经访问过的元素 则切换成下一个方向
+ let dirs = [
+ [0, 1], // 右
+ [1, 0], // 下
+ [0, -1], // 左
+ [-1, 0], // 上
+ ]
+
+ let currentDirIndex = 0
+
+ let visited = []
+ for (let y = 0; y < maxY; y++) {
+ visited[y] = []
+ }
+ let isValid = (y, x) => {
+ return y >= 0 && y < maxY && x >= 0 && x < maxX && !visited[y][x]
+ }
+
+ let targetLength = maxY * maxX
+ let res = []
+
+ let helper = (y, x) => {
+ let val = matrix[y][x]
+ res.push(val)
+
+ if (res.length === targetLength) {
+ return res
+ }
+
+ visited[y][x] = true
+ let [diffY, diffX] = dirs[currentDirIndex % 4]
+ let nextY = y + diffY
+ let nextX = x + diffX
+ if (!isValid(nextY, nextX)) {
+ [diffY, diffX] = dirs[++currentDirIndex % 4]
+ nextY = y + diffY
+ nextX = x + diffX
+ }
+ helper(nextY, nextX)
+ }
+
+ helper(0, 0)
+
+ return res
+};
\ No newline at end of file
diff --git "a/\351\200\222\345\275\222\344\270\216\345\233\236\346\272\257/\350\247\243\346\225\260\347\213\254-37.js" "b/\351\200\222\345\275\222\344\270\216\345\233\236\346\272\257/\350\247\243\346\225\260\347\213\254-37.js"
new file mode 100644
index 0000000..9bcf69e
--- /dev/null
+++ "b/\351\200\222\345\275\222\344\270\216\345\233\236\346\272\257/\350\247\243\346\225\260\347\213\254-37.js"
@@ -0,0 +1,87 @@
+/**
+ * @param {character[][]} board
+ * @return {void} Do not return anything, modify board in-place instead.
+ */
+let solveSudoku = function (board) {
+ let rows = initTwoDimensionalArray(9)
+ let columns = initTwoDimensionalArray(9)
+ let grids = initTwoDimensionalArray(3)
+
+ // 待处理下标队列 第一次扫描的时候记录下来
+ let pending = []
+
+ for (let y = 0; y < 9; y++) {
+ for (let x = 0; x < 9; x++) {
+ let cell = board[y][x]
+ if (cell === ".") {
+ // 待填充的数独格子 记录在队列中
+ pending.push([x, y])
+ continue
+ }
+ // 记录下当前下标
+ recordCell(x, y, cell)
+ }
+ }
+
+ let helper = (startPendingIndex) => {
+ if (startPendingIndex === pending.length) {
+ return true
+ }
+
+ let [x, y] = pending[startPendingIndex]
+
+ for (let i = 1; i <= 9; i++) {
+ let cur = i.toString()
+ if (isValid(x, y, cur)) {
+ board[y][x] = cur
+ recordCell(x, y, cur)
+ if (helper(startPendingIndex + 1)) {
+ return true
+ } else {
+ board[y][x] = "."
+ restoreCell(x, y, cur)
+ }
+ }
+ }
+ }
+
+ helper(0)
+
+ function recordCell(x, y, cell) {
+ rows[y][cell] = true
+ columns[x][cell] = true
+ let [gridX, gridY] = findGridIndex(x, y)
+ if (!grids[gridY][gridX]) {
+ grids[gridY][gridX] = new Map()
+ }
+ grids[gridY][gridX].set(cell, true)
+ }
+
+ function restoreCell(x, y, cell) {
+ rows[y][cell] = false
+ columns[x][cell] = false
+ let [gridX, gridY] = findGridIndex(x, y)
+ grids[gridY][gridX].set(cell, false)
+ }
+
+ function isValid(x, y, cell) {
+ let isYConflict = rows[y][cell]
+ let isXConflict = columns[x][cell]
+ let [gridX, gridY] = findGridIndex(x, y)
+ let grid = grids[gridY][gridX]
+ let isGridConflict = grid && grid.get(cell)
+ return !isYConflict && !isXConflict && !isGridConflict
+ }
+}
+
+function initTwoDimensionalArray(length) {
+ let ret = []
+ for (let i = 0; i < length; i++) {
+ ret.push([])
+ }
+ return ret
+}
+
+function findGridIndex(x, y) {
+ return [Math.floor(x / 3), Math.floor(y / 3)]
+}
diff --git "a/\351\200\222\345\275\222\344\270\216\345\233\236\346\272\257/\350\267\263\346\260\264\346\235\277-\351\235\242\350\257\225\351\242\230 16.11.js" "b/\351\200\222\345\275\222\344\270\216\345\233\236\346\272\257/\350\267\263\346\260\264\346\235\277-\351\235\242\350\257\225\351\242\230 16.11.js"
new file mode 100644
index 0000000..fb26019
--- /dev/null
+++ "b/\351\200\222\345\275\222\344\270\216\345\233\236\346\272\257/\350\267\263\346\260\264\346\235\277-\351\235\242\350\257\225\351\242\230 16.11.js"
@@ -0,0 +1,23 @@
+/**
+ * @param {number} shorter
+ * @param {number} longer
+ * @param {number} k
+ * @return {number[]}
+ */
+let divingBoard = function (shorter, longer, k) {
+ if (k === 0) {
+ return []
+ }
+ if (shorter === longer) {
+ return [k * shorter]
+ }
+
+ let res = []
+ for (let i = 0; i <= k; i++) {
+ let longCount = i
+ let shortCount = k - i
+ res.push(shortCount * shorter + longCount * longer)
+ }
+
+ return res
+};
\ No newline at end of file
diff --git "a/\351\200\222\345\275\222\344\270\216\345\233\236\346\272\257/\351\200\222\345\275\222\347\237\251\351\230\265-59.js" "b/\351\200\222\345\275\222\344\270\216\345\233\236\346\272\257/\351\200\222\345\275\222\347\237\251\351\230\265-59.js"
new file mode 100644
index 0000000..0be2940
--- /dev/null
+++ "b/\351\200\222\345\275\222\344\270\216\345\233\236\346\272\257/\351\200\222\345\275\222\347\237\251\351\230\265-59.js"
@@ -0,0 +1,54 @@
+/**
+ * @param {number} n
+ * @return {number[][]}
+ */
+let generateMatrix = function (n) {
+ // 记录一个 visited 数组
+ // 按照 右 -> 下 -> 左 -> 上 的方向不断前进
+ // 直到遇到边界或者已经访问过的元素 则切换成下一个方向
+ let dirs = [
+ [0, 1], // 右
+ [1, 0], // 下
+ [0, -1], // 左
+ [-1, 0], // 上
+ ]
+
+ let currentDirIndex = 0
+
+ let visited = []
+ for (let y = 0; y < n; y++) {
+ visited[y] = []
+ }
+ let isValid = (y, x) => {
+ return y >= 0 && y < n && x >= 0 && x < n && !visited[y][x]
+ }
+
+ let targetLength = n * n
+ let res = []
+ for (let y = 0; y < n; y++) {
+ res[y] = []
+ }
+
+ let helper = (y, x, num) => {
+ res[y][x] = num
+
+ if (num === targetLength) {
+ return res
+ }
+
+ visited[y][x] = true
+ let [diffY, diffX] = dirs[currentDirIndex % 4]
+ let nextY = y + diffY
+ let nextX = x + diffX
+ if (!isValid(nextY, nextX)) {
+ ;[diffY, diffX] = dirs[++currentDirIndex % 4]
+ nextY = y + diffY
+ nextX = x + diffX
+ }
+ helper(nextY, nextX, num + 1)
+ }
+
+ helper(0, 0, 1)
+
+ return res
+}
diff --git "a/\351\200\222\345\275\222\344\270\216\345\233\236\346\272\257/\351\241\272\346\254\241\346\225\260-1291.js" "b/\351\200\222\345\275\222\344\270\216\345\233\236\346\272\257/\351\241\272\346\254\241\346\225\260-1291.js"
new file mode 100644
index 0000000..13f8a5c
--- /dev/null
+++ "b/\351\200\222\345\275\222\344\270\216\345\233\236\346\272\257/\351\241\272\346\254\241\346\225\260-1291.js"
@@ -0,0 +1,30 @@
+/**
+ * @param {number} low
+ * @param {number} high
+ * @return {number[]}
+ */
+let sequentialDigits = function (low, high) {
+ let lowLen = low.toString().length
+ let highLen = high.toString().length
+ let lens = []
+ for (let i = lowLen; i <= highLen; i++) {
+ lens.push(i)
+ }
+
+ let res = []
+ for (let i = 0; i < lens.length; i++) {
+ let len = lens[i]
+ for (let start = 1; start <= 10 - len; start++) {
+ let num = start
+
+ for (let n = start + 1; n < start + len; n++) {
+ num = 10 * num + n
+ }
+ if (num <= high && num >= low) {
+ res.push(num)
+ }
+ }
+ }
+
+ return res
+}
\ No newline at end of file
diff --git "a/\351\200\222\345\275\222\344\270\216\345\233\236\346\272\257/\351\273\204\351\207\221\347\237\277\345\267\245-1219.js" "b/\351\200\222\345\275\222\344\270\216\345\233\236\346\272\257/\351\273\204\351\207\221\347\237\277\345\267\245-1219.js"
new file mode 100644
index 0000000..0d8d53c
--- /dev/null
+++ "b/\351\200\222\345\275\222\344\270\216\345\233\236\346\272\257/\351\273\204\351\207\221\347\237\277\345\267\245-1219.js"
@@ -0,0 +1,69 @@
+/**
+ * @param {number[][]} grid
+ * @return {number}
+ */
+let getMaximumGold = function (grid) {
+ let maxY = grid.length
+ if (maxY === 0) {
+ return 0
+ }
+ let maxX = grid[0].length
+
+ let visited = []
+ for (let y = 0; y < maxY; y++) {
+ visited[y] = []
+ }
+
+ let dirs = [
+ [1, 0],
+ [-1, 0],
+ [0, -1],
+ [0, 1],
+ ]
+
+ // 验证是否能走入这个格子
+ // 1. 范围不能越界
+ // 2. 本轮递归中未访问过
+ // 3. 格子的值不能为 0
+ let isValid = (y, x) => {
+ return (
+ y >= 0 &&
+ y < maxY &&
+ x >= 0 &&
+ x < maxX &&
+ grid[y][x] !== 0 &&
+ !visited[y][x]
+ )
+ }
+
+ let maxGold = 0
+ let helper = (y, x, prevGold) => {
+ let val = grid[y][x]
+ let curGold = prevGold + val
+ if (curGold === 0) {
+ return
+ }
+
+ for (let dir of dirs) {
+ let [diffY, diffX] = dir
+ let nextY = y + diffY
+ let nextX = x + diffX
+ if (isValid(nextY, nextX)) {
+ visited[y][x] = true
+ helper(nextY, nextX, curGold)
+ visited[y][x] = false
+ } else {
+ // 走到尽头或者不符合条件的了
+ maxGold = Math.max(maxGold, curGold)
+ }
+ }
+ }
+
+ for (let y = 0; y < maxY; y++) {
+ for (let x = 0; x < maxX; x++) {
+ helper(y, x, 0)
+ }
+ }
+
+ return maxGold
+}
diff --git "a/\351\223\276\350\241\250/\344\270\244\344\270\244\344\272\244\346\215\242\351\223\276\350\241\250\344\270\255\347\232\204\350\212\202\347\202\271-24.js" "b/\351\223\276\350\241\250/\344\270\244\344\270\244\344\272\244\346\215\242\351\223\276\350\241\250\344\270\255\347\232\204\350\212\202\347\202\271-24.js"
new file mode 100644
index 0000000..527b48a
--- /dev/null
+++ "b/\351\223\276\350\241\250/\344\270\244\344\270\244\344\272\244\346\215\242\351\223\276\350\241\250\344\270\255\347\232\204\350\212\202\347\202\271-24.js"
@@ -0,0 +1,28 @@
+const ListNode = require("../工具/链表")
+
+let swapPairs = function (head) {
+ let helper = function (node) {
+ let tempNext = node.next
+ if (tempNext) {
+ let tempNextNext = node.next.next
+ node.next.next = node
+ if (tempNextNext) {
+ node.next = helper(tempNextNext)
+ }else {
+ node.next = null
+ }
+ }
+ return tempNext
+ }
+
+ let res = helper(head)
+
+ return res
+}
+
+let node = new ListNode(1)
+node.next = new ListNode(2)
+node.next.next = new ListNode(3)
+node.next.next.next = new ListNode(4)
+
+console.log(swapPairs(node))
diff --git "a/\351\223\276\350\241\250/\344\270\244\346\225\260\347\233\270\345\212\240 II-445.js" "b/\351\223\276\350\241\250/\344\270\244\346\225\260\347\233\270\345\212\240 II-445.js"
new file mode 100644
index 0000000..477c5a7
--- /dev/null
+++ "b/\351\223\276\350\241\250/\344\270\244\346\225\260\347\233\270\345\212\240 II-445.js"
@@ -0,0 +1,69 @@
+var reverseList = function (head) {
+ if (!head) return null
+ let res = null
+ let dfs = function (node) {
+ if (node.next) {
+ dfs(node.next)
+ node.next.next = node
+ } else {
+ res = node
+ }
+ }
+
+ dfs(head)
+
+ head.next = null
+
+ return res
+};
+
+var addTwoNumbers = function (l1, l2) {
+ l1 = reverseList(l1)
+ l2 = reverseList(l2)
+
+ let i = 0
+ let root = new ListNode()
+ let cur = root
+ let plus = false
+
+ let traverse = (node1, node2) => {
+ let isDouble = !!node2
+ while (isDouble ? (node1 && node2) : node1) {
+ cur.next = new ListNode()
+ cur = cur.next
+
+ let sum = node1.val + (plus ? 1 : 0)
+ if (isDouble) {
+ sum += node2.val
+ }
+
+ if (sum >= 10) {
+ sum %= 10
+ plus = true
+ } else {
+ plus = false
+ }
+ cur.val = sum
+
+ node1 = node1.next
+ if (isDouble) {
+ node2 = node2.next
+ }
+ }
+
+ if (node1) {
+ traverse(node1)
+ }
+ if (node2) {
+ traverse(node2)
+ }
+ }
+
+ traverse(l1, l2)
+
+ if (plus) {
+ cur.next = new ListNode(1)
+ }
+
+ return reverseList(root.next)
+};
diff --git "a/\351\223\276\350\241\250/\344\270\244\346\225\260\347\233\270\345\212\240-3.js" "b/\351\223\276\350\241\250/\344\270\244\346\225\260\347\233\270\345\212\240-3.js"
new file mode 100644
index 0000000..9eec915
--- /dev/null
+++ "b/\351\223\276\350\241\250/\344\270\244\346\225\260\347\233\270\345\212\240-3.js"
@@ -0,0 +1,59 @@
+/**
+ * Definition for singly-linked list.
+ * function ListNode(val) {
+ * this.val = val;
+ * this.next = null;
+ * }
+ */
+/**
+ * @param {ListNode} l1
+ * @param {ListNode} l2
+ * @return {ListNode}
+ */
+let addTwoNumbers = function (l1, l2) {
+ let i = 0
+ let root = new ListNode()
+ let cur = root
+ let plus = false
+
+ let traverse = (node1, node2) => {
+ let isDouble = !!node2
+ while (isDouble ? node1 && node2 : node1) {
+ cur.next = new ListNode()
+ cur = cur.next
+
+ let sum = node1.val + (plus ? 1 : 0)
+ if (isDouble) {
+ sum += node2.val
+ }
+
+ if (sum >= 10) {
+ sum %= 10
+ plus = true
+ } else {
+ plus = false
+ }
+ cur.val = sum
+
+ node1 = node1.next
+ if (isDouble) {
+ node2 = node2.next
+ }
+ }
+
+ if (node1) {
+ traverse(node1)
+ }
+ if (node2) {
+ traverse(node2)
+ }
+ }
+
+ traverse(l1, l2)
+
+ if (plus) {
+ cur.next = new ListNode(1)
+ }
+
+ return root.next
+}
diff --git "a/\351\223\276\350\241\250/\345\210\240\351\231\244\351\223\276\350\241\250\344\270\255\347\232\204\350\212\202\347\202\271-\351\235\242\350\257\225\351\242\23018.js" "b/\351\223\276\350\241\250/\345\210\240\351\231\244\351\223\276\350\241\250\344\270\255\347\232\204\350\212\202\347\202\271-\351\235\242\350\257\225\351\242\23018.js"
new file mode 100644
index 0000000..611cb98
--- /dev/null
+++ "b/\351\223\276\350\241\250/\345\210\240\351\231\244\351\223\276\350\241\250\344\270\255\347\232\204\350\212\202\347\202\271-\351\235\242\350\257\225\351\242\23018.js"
@@ -0,0 +1,15 @@
+var deleteNode = function (head, val) {
+ let virtual = {
+ next: head,
+ }
+ let cur = virtual
+ while (cur) {
+ if (cur.next) {
+ if (cur.next.val === val) {
+ cur.next = cur.next.next
+ }
+ }
+ cur = cur.next
+ }
+ return virtual.next
+}
diff --git "a/\351\223\276\350\241\250/\345\210\240\351\231\244\351\223\276\350\241\250\347\232\204\345\200\222\346\225\260\347\254\254N\344\270\252\350\212\202\347\202\271-19.js" "b/\351\223\276\350\241\250/\345\210\240\351\231\244\351\223\276\350\241\250\347\232\204\345\200\222\346\225\260\347\254\254N\344\270\252\350\212\202\347\202\271-19.js"
new file mode 100644
index 0000000..3fa6ae6
--- /dev/null
+++ "b/\351\223\276\350\241\250/\345\210\240\351\231\244\351\223\276\350\241\250\347\232\204\345\200\222\346\225\260\347\254\254N\344\270\252\350\212\202\347\202\271-19.js"
@@ -0,0 +1,41 @@
+const { makeListNode } = require('../工具/链表')
+/**
+ * Definition for singly-linked list.
+ * function ListNode(val) {
+ * this.val = val;
+ * this.next = null;
+ * }
+ */
+/**
+ * @param {ListNode} head
+ * @param {number} n
+ * @return {ListNode}
+ */
+let removeNthFromEnd = function (head, n) {
+ let node = head
+ let nodes = []
+ do {
+ nodes.push(node)
+ node = node.next
+ } while (node)
+
+ const l = nodes.length
+ const index = l - n
+ const targetNode = nodes[index]
+ const prevNode = nodes[index - 1]
+ if (prevNode) {
+ prevNode.next = targetNode.next
+ }
+
+ const tempNext = targetNode.next
+ targetNode.next = null
+
+
+ if (targetNode === head) {
+ return tempNext
+ }
+ return head
+};
+
+const node = makeListNode([1, 2, 3, 4, 5])
+console.log(removeNthFromEnd(node, 5))
\ No newline at end of file
diff --git "a/\351\223\276\350\241\250/\345\217\215\350\275\254\351\223\276\350\241\250-206.js" "b/\351\223\276\350\241\250/\345\217\215\350\275\254\351\223\276\350\241\250-206.js"
new file mode 100644
index 0000000..32097f9
--- /dev/null
+++ "b/\351\223\276\350\241\250/\345\217\215\350\275\254\351\223\276\350\241\250-206.js"
@@ -0,0 +1,13 @@
+function reverse(head) {
+ let prev = null
+ let cur = head
+ while (cur) {
+ let next = cur.next
+ cur.next = prev
+
+ prev = cur
+ cur = next
+ }
+ // 返回反转后的头节点
+ return prev
+}
diff --git "a/\351\223\276\350\241\250/\345\217\215\350\275\254\351\223\276\350\241\250II-92.js" "b/\351\223\276\350\241\250/\345\217\215\350\275\254\351\223\276\350\241\250II-92.js"
new file mode 100644
index 0000000..ab69981
--- /dev/null
+++ "b/\351\223\276\350\241\250/\345\217\215\350\275\254\351\223\276\350\241\250II-92.js"
@@ -0,0 +1,74 @@
+/**
+ * Definition for singly-linked list.
+ * function ListNode(val) {
+ * this.val = val;
+ * this.next = null;
+ * }
+ */
+
+const ListNode = require("../工具/链表")
+/**
+ * @param {ListNode} head
+ * @param {number} m
+ * @param {number} n
+ * @return {ListNode}
+ */
+
+let reverseBetween = function (head, m, n) {
+ let i = 1
+ let sliceStartPrev = null
+ let sliceStart = null
+ let sliceEnd = null
+ let cur = head
+
+ // 记录切分起点的前一个节点,和切分终点的后一个节点
+ while (i <= n) {
+ if (i === m - 1) {
+ sliceStartPrev = cur
+ }
+ if (i === m) {
+ sliceStart = cur
+ }
+ if (i === n) {
+ sliceEnd = cur
+ }
+ cur = cur.next
+ i++
+ }
+
+ let sliceEndNext = sliceEnd.next
+ // 切断切分终点的next 防止反转的时候反转过头
+ sliceEnd.next = null
+
+ const { head: slicedHead, tail: slicedTail } = reverse(sliceStart)
+ if (sliceStartPrev) {
+ // 如果需要反转的部分有前一个节点 那么只需要在中间动手脚 原样返回head节点即可
+ sliceStartPrev.next = slicedHead
+ } else {
+ // 这里需要注意的是 如果没有sliceStartPrev 说明是从第一个节点就开始反转的
+ // 那么我们需要手动调整head为反转后的head
+ head = slicedHead
+ }
+ slicedTail.next = sliceEndNext
+
+ return head
+}
+
+function reverse(head) {
+ let prev = null
+ let cur = head
+ while (cur) {
+ let next = cur.next
+ cur.next = prev
+
+ prev = cur
+ cur = next
+ }
+ // 返回反转后的头尾节点
+ return { head: prev, tail: head }
+}
+
+let node = new ListNode(3)
+node.next = new ListNode(5)
+
+console.log(JSON.stringify(reverseBetween(node, 1, 1)))
diff --git "a/\351\223\276\350\241\250/\347\247\273\351\231\244\351\223\276\350\241\250\345\205\203\347\264\240-203.js" "b/\351\223\276\350\241\250/\347\247\273\351\231\244\351\223\276\350\241\250\345\205\203\347\264\240-203.js"
new file mode 100644
index 0000000..bd16019
--- /dev/null
+++ "b/\351\223\276\350\241\250/\347\247\273\351\231\244\351\223\276\350\241\250\345\205\203\347\264\240-203.js"
@@ -0,0 +1,18 @@
+let removeElements = function (head, val) {
+ let root = new ListNode()
+ root.next = head
+ let cur = root
+ while (cur) {
+ let next = cur.next
+ if (!next) {
+ break
+ }
+ let nextVal = next.val
+ if (nextVal === val) {
+ cur.next = cur.next.next
+ } else {
+ cur = cur.next
+ }
+ }
+ return root.next
+}
diff --git "a/\347\256\227\346\263\225/\351\252\214\350\257\201\345\233\236\346\226\207\345\255\227\347\254\246\344\270\2622.js" "b/\351\252\214\350\257\201\345\233\236\346\226\207\345\255\227\347\254\246\344\270\2622.js"
similarity index 57%
rename from "\347\256\227\346\263\225/\351\252\214\350\257\201\345\233\236\346\226\207\345\255\227\347\254\246\344\270\2622.js"
rename to "\351\252\214\350\257\201\345\233\236\346\226\207\345\255\227\347\254\246\344\270\2622.js"
index 1e19f23..2f1b015 100644
--- "a/\347\256\227\346\263\225/\351\252\214\350\257\201\345\233\236\346\226\207\345\255\227\347\254\246\344\270\2622.js"
+++ "b/\351\252\214\350\257\201\345\233\236\346\226\207\345\255\227\347\254\246\344\270\2622.js"
@@ -2,36 +2,36 @@
* @param {string} s
* @return {boolean}
*/
-var validPalindrome = function(s) {
- var i = 0;
- var j = s.length - 1
-
+let validPalindrome = function (s) {
+ let i = 0;
+ let j = s.length - 1;
+
// 两个指针往中间缩进
while (i < j && s[i] === s[j]) {
- i++
- j--
+ i++;
+ j--;
}
// 遇到相对位置不相等了 判断删除一位后的情况
if (isPalindrome(i + 1, j)) {
- return true
+ return true;
}
if (isPalindrome(i, j - 1)) {
- return true
+ return true;
}
// 工具方法,用于判断字符串是否回文
function isPalindrome(st, ed) {
- while(st lastIndex) {
// lastIndex = finded + slicedCount
// sliced = sliced.substr(finded + 1)
@@ -29,7 +29,7 @@ s = "abc", t = "ahbgdc"
// }
// 这种是速度最快的 利用indexOf的第二个参数做起点
-var isSubsequence = function(s, t) {
+let isSubsequence = function(s, t) {
let start=0
for(let i=0; i < s.length; i++) {
let index = t.indexOf(s[i], start)
@@ -39,6 +39,6 @@ var isSubsequence = function(s, t) {
return true
};
-var a = "leeeeetcode"
-var b = 'leeeeeeeeeeccccctcccoddddeeee'
+let a = "leeeeetcode"
+let b = 'leeeeeeeeeeccccctcccoddddeeee'
console.log(isSubsequence(a, b))
\ No newline at end of file
diff --git "a/\347\256\227\346\263\225/\351\252\214\350\257\201\345\271\263\350\241\241\344\272\214\345\217\211\346\240\221.js" "b/\351\252\214\350\257\201\345\271\263\350\241\241\344\272\214\345\217\211\346\240\221.js"
similarity index 93%
rename from "\347\256\227\346\263\225/\351\252\214\350\257\201\345\271\263\350\241\241\344\272\214\345\217\211\346\240\221.js"
rename to "\351\252\214\350\257\201\345\271\263\350\241\241\344\272\214\345\217\211\346\240\221.js"
index 36d75b6..1cc93a8 100644
--- "a/\347\256\227\346\263\225/\351\252\214\350\257\201\345\271\263\350\241\241\344\272\214\345\217\211\346\240\221.js"
+++ "b/\351\252\214\350\257\201\345\271\263\350\241\241\344\272\214\345\217\211\346\240\221.js"
@@ -1,9 +1,9 @@
-var isValidBST = function(root) {
+let isValidBST = function(root) {
function helper(node, lower, upper) {
// 遇到空节点 直接返回true
if (!node) return true
- var val = node.val
+ let val = node.val
// 如果当前的值比下边界还小 就失败
if (lower !== null && val <= lower) return false
// 如果当前的值比上边界还大 就失败