├── .gitignore ├── .eslintignore ├── .DS_Store ├── src ├── .DS_Store ├── lodash │ ├── compact.js │ ├── 实现链式调用.js │ ├── compose-fp.js │ ├── difference.js │ ├── pointfree.js │ ├── range.js │ ├── debounce.js │ ├── throttle.js │ ├── compose.js │ ├── memoized.js │ ├── strongThrottle.js │ ├── add(1)(2)(3).js │ ├── chunk.js │ ├── curry.js │ ├── observer.js │ ├── iterable.js │ ├── get.js │ └── 洋葱模型.js ├── 4.array │ ├── 28.有序数组的平方.js │ ├── 32.斐波那契数列.js │ ├── 30.丢失的数字.js │ ├── 27.一组数组的动态和.js │ ├── 21.0~n-1中缺失的数字.js │ ├── 11.买卖股票的最佳时机2.js │ ├── 16.判定字符是否唯一.js │ ├── 4.搜索插入位置.js │ ├── 17.存在重复元素.js │ ├── 2.删除有序数组的重复项.js │ ├── 3.移出元素.js │ ├── 31.在排序数组中查找数字 I.js │ ├── 6.买卖股票的最佳时机.js │ ├── 12.数组中重复的数字.js │ ├── 5.合并排序的数组.js │ ├── 22.拥有最多糖果的孩子.js │ ├── 1.两数之和.js │ ├── 10.合并两个有序数组.js │ ├── 8.移动零.js │ ├── 9.加一.js │ ├── 24.使用最小花费爬楼梯.js │ ├── 19.有多少小于当前数字的数字.js │ ├── 25.数组的相对顺序.js │ ├── 33.存在重复元素 II.js │ ├── 14.杨辉三角.js │ ├── 29.按奇偶排序数组 II.js │ ├── 13.多数元素.js │ ├── 26.杨辉三角2.js │ ├── 23.拼写单词.js │ ├── 20.将数组分成和相等的三个部分.js │ ├── 15.两数之和.js │ ├── 7.最大子序的和.js │ └── 18.顺时针打印矩阵.js ├── 7.hash-table │ ├── 4.有效的字母异位词.js │ ├── 2.数组中重复的数字.js │ ├── 5.最长回文串.js │ ├── 1.两数之和.js │ └── 3.只出现一次的数字.js ├── 3.string │ ├── 14.翻转字符串中的单词.js │ ├── 5.外观数列.js │ ├── 6.最后一个单词的长度.js │ ├── 8.二进制和.js │ ├── 12.匹配字符串中的数字.js │ ├── 10.左旋转字符串.js │ ├── 9.翻转字符串.js │ ├── 15.判定是否互为字符重排.js │ ├── 7.验证回文串.js │ ├── 4.实现strStr().js │ ├── 13.字符串中唯一字符.js │ ├── 2.最长公共前缀.js │ ├── 3.罗马数字转整数.js │ ├── 1.有效括号.js │ ├── 16.字符串相加.js │ └── 11.字符串压缩.js ├── 1.stack │ ├── 6..删除字符串中的所有相邻重复项.js │ ├── 4.最近的请求次数.js │ ├── 8.文件夹操作日志搜索器.js │ ├── 15.比较含退格的字符串.js │ ├── 7.棒球比赛.js │ ├── 1.删除最外层的括号.js │ ├── 3.有效的括号.js │ ├── 2.用两个栈实现队列.js │ ├── 17.滑动窗口最大的值.js │ ├── 12.包含min函数的栈.js │ ├── 13.栈的最小值.js │ ├── 14.最小栈.js │ ├── 5.化栈为队.js │ ├── 10.用队列实现栈.js │ ├── 11.用栈操作构建数组.js │ ├── 16.整理字符串.js │ └── 9.下一个更大元素.js ├── 5.linked-list │ ├── 14.删除链表中的节点.js │ ├── 19.删除中间节点.js │ ├── 6.从尾到头打印链表.js │ ├── 9.反转链表.js │ ├── 17.二进制链表转整数.js │ ├── 1.翻转链表.js │ ├── 15.返回倒数第 k 个节点.js │ ├── 10.删除排序链表中的重复元素.js │ ├── 20.回文链表.js │ ├── 12.删除链表的节点.js │ ├── 8.相交链表.js │ ├── 21.链表相交.js │ ├── 18.两个链表的第一个公共节点.js │ ├── 16.移除重复节点.js │ ├── 4.回文链表.js │ ├── 13.移出链表元素.js │ ├── 3.环形链表.js │ ├── 7.链表的中间节点.js │ ├── 2.合并两个有序的链表.js │ └── 5.链表中倒数第k个节点.js ├── 6.binary-tree │ ├── 13.二叉树的深度.js │ ├── 11.二叉树的镜像.js │ ├── 25.N叉树的最大深度.js │ ├── 1.二叉树的最大深度.js │ ├── 16.二叉搜索树的第k大节点.js │ ├── 27.二叉搜索树的最近公共祖先.js │ ├── 19.平衡二叉树.js │ ├── 18.对称的二叉树.js │ ├── 5.翻转二叉树.js │ ├── 3.相同的树.js │ ├── 12.合并二叉树.js │ ├── 26.N 叉树的前序遍历.js │ ├── 24.二叉树的最近公共祖先.js │ ├── 6.路径总和.js │ ├── 9.二叉树的直径.js │ ├── 17.从上到下打印二叉树 II.js │ ├── 7.左叶子之和.js │ ├── 22.二叉搜索树的最小绝对差.js │ ├── 23.二叉搜索树中的众数.js │ ├── 28.二叉搜索树的范围和.js │ ├── 7.平衡二叉树.js │ ├── 10.将有序数组转换为二叉搜索树.js │ ├── 2.对称二叉树.js │ ├── 8.二叉树层次遍历.js │ ├── 21.二叉树的层平均值.js │ ├── 20.另一个树的子树.js │ ├── 4.二叉树最小深度.js │ ├── 15.二叉搜索树的最近公共祖先.js │ └── 14.二叉树的所有路径.js ├── 2.queue │ ├── 1.最近的请求次数.js │ └── 2.滑动窗口最大的值.js ├── Promise │ ├── generator.js │ ├── test.js │ ├── promise.js │ └── myPromise.js └── nativeJS │ ├── apply.js │ ├── call.js │ └── bind.js ├── .eslintrc.js ├── README.md ├── package.json └── .eslintcache /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mengbo-ji/leetcode-js-roadmap/HEAD/.DS_Store -------------------------------------------------------------------------------- /src/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mengbo-ji/leetcode-js-roadmap/HEAD/src/.DS_Store -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: 'eslint-config-rc', 3 | rules: { 4 | 'no-unused-vars': [ 'off' ], 5 | 'no-bitwise': [ 'off' ], 6 | }, 7 | }; 8 | -------------------------------------------------------------------------------- /src/lodash/compact.js: -------------------------------------------------------------------------------- 1 | const _ = require('lodash'); 2 | 3 | const arr = [ 0, 1, false, 2, '', 3 ]; 4 | console.log(_.compact(arr)); 5 | 6 | // native 7 | const _arr = arr.filter(Boolean); 8 | console.log(_arr); 9 | -------------------------------------------------------------------------------- /src/lodash/实现链式调用.js: -------------------------------------------------------------------------------- 1 | const obj = { 2 | a() { 3 | console.log('a'); 4 | return this; 5 | }, 6 | b() { 7 | console.log('b'); 8 | return this; 9 | }, 10 | }; 11 | 12 | obj.a().b(); 13 | -------------------------------------------------------------------------------- /src/4.array/28.有序数组的平方.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[]} nums 3 | * @return {number[]} 4 | */ 5 | const sortedSquares = function(nums) { 6 | return nums.map(v => (v = Math.pow(v, 2))).sort((a, b) => a - b); 7 | }; 8 | -------------------------------------------------------------------------------- /src/lodash/compose-fp.js: -------------------------------------------------------------------------------- 1 | // loadsh fp 模块 2 | // 函数在前、数据在后 3 | // NEVER SAY DIE --> never-say-die 4 | const fp = require('lodash/fp'); 5 | const f = fp.flowRight(fp.join('-'), fp.map(fp.toLower), fp.split(' ')); 6 | 7 | console.log(f('NEVER SAY DIE')); 8 | -------------------------------------------------------------------------------- /src/4.array/32.斐波那契数列.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number} n 3 | * @return {number} 4 | */ 5 | const fib = function(n) { 6 | if (n === 0) { 7 | return 0; 8 | } 9 | if (n === 1 || n === 2) { 10 | return 1; 11 | } 12 | return fib(n - 1) + fib(n - 2); 13 | }; 14 | -------------------------------------------------------------------------------- /src/7.hash-table/4.有效的字母异位词.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {string} s 3 | * @param {string} t 4 | * @return {boolean} 5 | */ 6 | const isAnagram = function(s, t) { 7 | if (s.length !== t.length) return false; 8 | return [ ...s ].sort().join('') === [ ...t ].sort().join(''); 9 | }; 10 | -------------------------------------------------------------------------------- /src/3.string/14.翻转字符串中的单词.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {string} s 3 | * @return {string} 4 | */ 5 | const reverseWords = function(s) { 6 | const arr = s.split(' '); 7 | const res = arr.map(v => { 8 | return v.split('').reverse().join(''); 9 | }); 10 | return res.join(' '); 11 | }; 12 | -------------------------------------------------------------------------------- /src/4.array/30.丢失的数字.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[]} nums 3 | * @return {number} 4 | */ 5 | const missingNumber = function(nums) { 6 | nums.sort((a, b) => a - b); 7 | for (let i = 0; i <= nums.length; i++) { 8 | if (i !== nums[i]) { 9 | return i; 10 | } 11 | } 12 | }; 13 | -------------------------------------------------------------------------------- /src/4.array/27.一组数组的动态和.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[]} nums 3 | * @return {number[]} 4 | */ 5 | const runningSum = function(nums) { 6 | const sum = []; 7 | nums.reduce((prev, next) => { 8 | sum.push(prev + next); 9 | return prev + next; 10 | }, 0); 11 | 12 | return sum; 13 | }; 14 | -------------------------------------------------------------------------------- /src/7.hash-table/2.数组中重复的数字.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[]} nums 3 | * @return {number} 4 | */ 5 | const findRepeatNumber = function(nums) { 6 | const map = new Map(); 7 | for (const v of nums) { 8 | if (map.has(v)) { 9 | return v; 10 | } 11 | map.set(v, v); 12 | } 13 | }; 14 | -------------------------------------------------------------------------------- /src/4.array/21.0~n-1中缺失的数字.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[]} nums 3 | * @return {number} 4 | */ 5 | const missingNumber = function(nums) { 6 | // 防止缺失的一个 7 | nums.push('x'); 8 | for (let i = 0; i < nums.length; i++) { 9 | if (nums[i] !== i) { 10 | return i; 11 | } 12 | } 13 | }; 14 | -------------------------------------------------------------------------------- /src/lodash/difference.js: -------------------------------------------------------------------------------- 1 | const _ = require('lodash'); 2 | console.log(_.difference([ 3, 2, 1 ], [ 4, 2 ])); 3 | 4 | // native 5 | const _difference = (arr1, arr2) => { 6 | return arr1.filter(v => !arr2.includes(v)); 7 | }; 8 | 9 | console.log('_difference', _difference([ 3, 2, 1 ], [ 4, 2, 1 ])); 10 | -------------------------------------------------------------------------------- /src/3.string/5.外观数列.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number} n 3 | * @return {string} 4 | */ 5 | const countAndSay = function(n) { 6 | let prev = '1'; 7 | for (let i = 1; i < n; i++) { 8 | // 正则重复匹配数字 9 | prev = prev.replace(/(\d)\1*/g, item => `${item.length}${item[0]}`); 10 | } 11 | return prev; 12 | }; 13 | -------------------------------------------------------------------------------- /src/3.string/6.最后一个单词的长度.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {string} s 3 | * @return {number} 4 | */ 5 | const lengthOfLastWord = function(s) { 6 | const arr = s.split(' '); 7 | for (let i = arr.length - 1; i >= 0; i--) { 8 | if (arr[i]) { 9 | return arr[i].length; 10 | } 11 | } 12 | return 0; 13 | }; 14 | -------------------------------------------------------------------------------- /src/4.array/11.买卖股票的最佳时机2.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[]} prices 3 | * @return {number} 4 | */ 5 | const maxProfit = function(prices) { 6 | // 贪心算法 只要赚钱就加 7 | let sum = 0; 8 | for (let i = 1; i < prices.length; i++) { 9 | sum += Math.max(0, prices[i] - prices[i - 1]); 10 | } 11 | return sum; 12 | }; 13 | -------------------------------------------------------------------------------- /src/4.array/16.判定字符是否唯一.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {string} astr 3 | * @return {boolean} 4 | */ 5 | const isUnique = function(astr) { 6 | const map = new Map(); 7 | for (const v of astr) { 8 | if (map.has(v)) { 9 | return false; 10 | } 11 | map.set(v, v); 12 | 13 | } 14 | return true; 15 | }; 16 | -------------------------------------------------------------------------------- /src/4.array/4.搜索插入位置.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[]} nums 3 | * @param {number} target 4 | * @return {number} 5 | */ 6 | const searchInsert = function(nums, target) { 7 | for (let i = 0; i < nums.length; i++) { 8 | if (target <= nums[i]) { 9 | return i; 10 | } 11 | } 12 | return nums.length; 13 | }; 14 | -------------------------------------------------------------------------------- /src/4.array/17.存在重复元素.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[]} nums 3 | * @return {boolean} 4 | */ 5 | const containsDuplicate = function(nums) { 6 | const map = new Map(); 7 | for (const v of nums) { 8 | if (map.has(v)) { 9 | return true; 10 | } 11 | map.set(v, v); 12 | 13 | } 14 | return false; 15 | }; 16 | -------------------------------------------------------------------------------- /src/4.array/2.删除有序数组的重复项.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[]} nums 3 | * @return {number} 4 | */ 5 | const removeDuplicates = function(nums) { 6 | let i = 0; 7 | for (let j = 1; j < nums.length; j++) { 8 | if (nums[j] !== nums[i]) { 9 | i++; 10 | nums[i] = nums[j]; 11 | } 12 | } 13 | return i + 1; 14 | }; 15 | -------------------------------------------------------------------------------- /src/3.string/8.二进制和.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {string} a 3 | * @param {string} b 4 | * @return {string} 5 | */ 6 | const addBinary = function(a, b) { 7 | // const res = (parseInt(a,2) + parseInt(b,2)).toString(2) 8 | // 用Bigint防止益处 9 | const res = (BigInt('0b' + a) + BigInt('0b' + b)).toString(2); 10 | 11 | return res; 12 | }; 13 | -------------------------------------------------------------------------------- /src/4.array/3.移出元素.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[]} nums 3 | * @param {number} val 4 | * @return {number} 5 | */ 6 | const removeElement = function(nums, val) { 7 | for (let i = 0; i < nums.length; i++) { 8 | if (nums[i] === val) { 9 | nums.splice(i, 1); 10 | i--; 11 | } 12 | } 13 | return nums.length; 14 | }; 15 | -------------------------------------------------------------------------------- /src/4.array/31.在排序数组中查找数字 I.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[]} nums 3 | * @param {number} target 4 | * @return {number} 5 | */ 6 | const search = function(nums, target) { 7 | let sum = 0; 8 | for (let i = 0; i < nums.length; i++) { 9 | if (nums[i] === target) { 10 | sum += 1; 11 | } 12 | } 13 | return sum; 14 | }; 15 | -------------------------------------------------------------------------------- /src/3.string/12.匹配字符串中的数字.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {string} s 3 | * @return {string} 4 | */ 5 | const s = '/2222/aaaa/4/inde11x.html'; 6 | const findNumber = function(s) { 7 | let res = ''; 8 | const arr = s.match(/(\/\d+\/)\1*/g); 9 | if (arr) { 10 | res = arr[0].substring(1, arr[0].length - 1); 11 | } 12 | return arr; 13 | }; 14 | -------------------------------------------------------------------------------- /src/3.string/10.左旋转字符串.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {string} s 3 | * @param {number} n 4 | * @return {string} 5 | */ 6 | const reverseLeftWords = function(s, n) { 7 | let str = s.substring(n); 8 | let index = 1; 9 | while (n) { 10 | str = str + s.substring(index - 1, index); 11 | index++; 12 | n--; 13 | } 14 | return str; 15 | }; 16 | -------------------------------------------------------------------------------- /src/4.array/6.买卖股票的最佳时机.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[]} prices 3 | * @return {number} 4 | */ 5 | const maxProfit = function(prices) { 6 | let max = 0, 7 | min = prices[0]; 8 | for (let i = 0; i < prices.length; i++) { 9 | min = Math.min(min, prices[i]); 10 | max = Math.max(max, prices[i] - min); 11 | } 12 | return max; 13 | }; 14 | -------------------------------------------------------------------------------- /src/4.array/12.数组中重复的数字.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[]} nums 3 | * @return {number} 4 | */ 5 | const findRepeatNumber = function(nums) { 6 | const map = new Map(); 7 | for (let i = 0; i < nums.length; i++) { 8 | if (map.get(nums[i]) || map.get(nums[i]) === 0) { 9 | return nums[i]; 10 | } 11 | map.set(nums[i], nums[i]); 12 | 13 | } 14 | }; 15 | -------------------------------------------------------------------------------- /src/1.stack/6..删除字符串中的所有相邻重复项.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {string} S 3 | * @return {string} 4 | */ 5 | const removeDuplicates = function(s) { 6 | const stack = []; 7 | for (let i = 0; i < s.length; i++) { 8 | if (stack[stack.length - 1] !== s[i]) { 9 | stack.push(s[i]); 10 | } else { 11 | stack.pop(); 12 | } 13 | } 14 | return stack.join(''); 15 | }; 16 | -------------------------------------------------------------------------------- /src/3.string/9.翻转字符串.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {character[]} s 3 | * @return {void} Do not return anything, modify s in-place instead. 4 | */ 5 | const reverseString = function(s) { 6 | let left = 0; 7 | let right = s.length - 1; 8 | while (left < right) { 9 | [ s[left], s[right] ] = [ s[right], s[left] ]; 10 | left++; 11 | right--; 12 | } 13 | return s; 14 | }; 15 | -------------------------------------------------------------------------------- /src/4.array/5.合并排序的数组.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[]} A 3 | * @param {number} m 4 | * @param {number[]} B 5 | * @param {number} n 6 | * @return {void} Do not return anything, modify A in-place instead. 7 | */ 8 | const merge = function(A, m, B, n) { 9 | A.splice(m); 10 | for (let i = 0; i < n; i++) { 11 | A.push(B[i]); 12 | } 13 | return A.sort((a, b) => a - b); 14 | }; 15 | -------------------------------------------------------------------------------- /src/4.array/22.拥有最多糖果的孩子.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[]} candies 3 | * @param {number} extraCandies 4 | * @return {boolean[]} 5 | */ 6 | const kidsWithCandies = function(candies, extraCandies) { 7 | const max = Math.max(...candies); 8 | return candies.map(v => { 9 | if (v + extraCandies >= max) { 10 | return true; 11 | } 12 | return false; 13 | 14 | }); 15 | }; 16 | -------------------------------------------------------------------------------- /src/lodash/pointfree.js: -------------------------------------------------------------------------------- 1 | // 把一个字符串中的首字母提取并转换成大写,使用. 作为分隔符 2 | // world wild web --> W. W. W. 3 | 4 | const fp = require('lodash/fp'); 5 | 6 | 7 | // const f = fp.flowRight(fp.join('. '), fp.map(fp.toUpper), fp.map(fp.first), fp.split(' ')); 8 | const f = fp.flowRight(fp.join('. '), fp.map(fp.flowRight(fp.toUpper, fp.first)), fp.split(' ')); 9 | 10 | console.log(f('world wild web')); 11 | 12 | -------------------------------------------------------------------------------- /src/4.array/1.两数之和.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[]} nums 3 | * @param {number} target 4 | * @return {number[]} 5 | */ 6 | const twoSum = function(nums, target) { 7 | const map = new Map(); 8 | for (let i = 0; i < nums.length; i++) { 9 | if (map.has(target - nums[i])) { 10 | return [ map.get(target - nums[i]), i ]; 11 | } 12 | map.set(nums[i], i); 13 | 14 | } 15 | }; 16 | -------------------------------------------------------------------------------- /src/7.hash-table/5.最长回文串.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {string} s 3 | * @return {number} 4 | */ 5 | const longestPalindrome = function(s) { 6 | let sum = 0; 7 | const set = new Set(); 8 | s.split('').forEach(v => { 9 | if (set.has(v)) { 10 | set.delete(v); 11 | sum += 2; 12 | } else { 13 | set.add(v); 14 | } 15 | }); 16 | return sum + (set.size > 0 ? 1 : 0); 17 | }; 18 | -------------------------------------------------------------------------------- /src/7.hash-table/1.两数之和.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[]} nums 3 | * @param {number} target 4 | * @return {number[]} 5 | */ 6 | const twoSum = function(nums, target) { 7 | const map = new Map(); 8 | for (let i = 0; i < nums.length; i++) { 9 | const cur = target - nums[i]; 10 | if (map.has(cur)) { 11 | return [ map.get(cur), i ]; 12 | } 13 | map.set(nums[i], i); 14 | } 15 | }; 16 | -------------------------------------------------------------------------------- /src/4.array/10.合并两个有序数组.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[]} nums1 3 | * @param {number} m 4 | * @param {number[]} nums2 5 | * @param {number} n 6 | * @return {void} Do not return anything, modify nums1 in-place instead. 7 | */ 8 | const merge = function(nums1, m, nums2, n) { 9 | nums1.splice(m); 10 | nums2.forEach(v => { 11 | nums1.push(v); 12 | }); 13 | return nums1.sort((a, b) => a - b); 14 | }; 15 | -------------------------------------------------------------------------------- /src/4.array/8.移动零.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[]} nums 3 | * @return {void} Do not return anything, modify nums in-place instead. 4 | */ 5 | const moveZeroes = function(nums) { 6 | let len = nums.length; 7 | for (let i = 0; i < len; i++) { 8 | if (nums[i] === 0) { 9 | nums.splice(i, 1); 10 | nums.push(0); 11 | i--; 12 | len--; 13 | } 14 | } 15 | return nums; 16 | }; 17 | -------------------------------------------------------------------------------- /src/4.array/9.加一.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[]} digits 3 | * @return {number[]} 4 | */ 5 | const plusOne = function(digits) { 6 | let carry = false; 7 | digits[digits.length - 1]++; 8 | for (let i = digits.length - 1; i >= 0; i--) { 9 | if (carry) digits[i]++; 10 | carry = digits[i] > 9; 11 | digits[i] = digits[i] % 10; 12 | } 13 | if (carry) digits.unshift(1); 14 | return digits; 15 | }; 16 | -------------------------------------------------------------------------------- /src/5.linked-list/14.删除链表中的节点.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for singly-linked list. 3 | * function ListNode(val) { 4 | * this.val = val; 5 | * this.next = null; 6 | * } 7 | */ 8 | /** 9 | * @param {ListNode} node 10 | * @return {void} Do not return anything, modify node in-place instead. 11 | */ 12 | const deleteNode = function(node) { 13 | node.val = node.next.val; 14 | node.next = node.next.next; 15 | }; 16 | -------------------------------------------------------------------------------- /src/5.linked-list/19.删除中间节点.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for singly-linked list. 3 | * function ListNode(val) { 4 | * this.val = val; 5 | * this.next = null; 6 | * } 7 | */ 8 | /** 9 | * @param {ListNode} node 10 | * @return {void} Do not return anything, modify node in-place instead. 11 | */ 12 | const deleteNode = function(node) { 13 | node.val = node.next.val; 14 | node.next = node.next.next; 15 | }; 16 | -------------------------------------------------------------------------------- /src/4.array/24.使用最小花费爬楼梯.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[]} cost 3 | * @return {number} 4 | */ 5 | const minCostClimbingStairs = function(cost) { 6 | // 当前 = Math.min(前一步 + 前两步) + cost[i] 7 | let prev = cost[0], 8 | curr = cost[1]; 9 | for (let i = 2; i <= cost.length; i++) { 10 | const next = Math.min(prev, curr) + (cost[i] || 0); 11 | prev = curr; 12 | curr = next; 13 | } 14 | return curr; 15 | }; 16 | -------------------------------------------------------------------------------- /src/6.binary-tree/13.二叉树的深度.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for a binary tree node. 3 | * function TreeNode(val) { 4 | * this.val = val; 5 | * this.left = this.right = null; 6 | * } 7 | */ 8 | /** 9 | * @param {TreeNode} root 10 | * @return {number} 11 | */ 12 | const maxDepth = function(root) { 13 | // 终止条件 14 | if (!root) return 0; 15 | 16 | return Math.max(maxDepth(root.left), maxDepth(root.right)) + 1; 17 | }; 18 | -------------------------------------------------------------------------------- /src/3.string/15.判定是否互为字符重排.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {string} s1 3 | * @param {string} s2 4 | * @return {boolean} 5 | */ 6 | const CheckPermutation = function(s1, s2) { 7 | const res1 = s1.split('').sort((a, b) => { 8 | return a.charCodeAt(0) - b.charCodeAt(0); 9 | }); 10 | const res2 = s2.split('').sort((a, b) => { 11 | return a.charCodeAt(0) - b.charCodeAt(0); 12 | }); 13 | return res1.join('') === res2.join(''); 14 | }; 15 | -------------------------------------------------------------------------------- /src/5.linked-list/6.从尾到头打印链表.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for singly-linked list. 3 | * function ListNode(val) { 4 | * this.val = val; 5 | * this.next = null; 6 | * } 7 | */ 8 | /** 9 | * @param {ListNode} head 10 | * @return {number[]} 11 | */ 12 | const reversePrint = function(head) { 13 | const list = []; 14 | while (head) { 15 | list.unshift(head.val); 16 | head = head.next; 17 | } 18 | return list; 19 | }; 20 | -------------------------------------------------------------------------------- /src/3.string/7.验证回文串.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {string} s 3 | * @return {boolean} 4 | */ 5 | const isPalindrome = function(s) { 6 | const arr = s.toLowerCase().match(/[A-Za-z0-9]+/g); 7 | if (!arr) return true; 8 | const str = arr.join(''); 9 | let left = 0; 10 | let right = str.length - 1; 11 | while (left < right) { 12 | if (str[left] !== str[right]) return false; 13 | left++; 14 | right--; 15 | } 16 | return true; 17 | }; 18 | -------------------------------------------------------------------------------- /src/4.array/19.有多少小于当前数字的数字.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[]} nums 3 | * @return {number[]} 4 | */ 5 | const smallerNumbersThanCurrent = function(nums) { 6 | const res = []; 7 | for (let i = 0; i < nums.length; i++) { 8 | let len = 0; 9 | for (let j = 0; j < nums.length; j++) { 10 | if (i !== j && nums[j] < nums[i]) { 11 | len++; 12 | } 13 | } 14 | res.push(len); 15 | len = 0; 16 | } 17 | return res; 18 | }; 19 | -------------------------------------------------------------------------------- /src/4.array/25.数组的相对顺序.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[]} arr1 3 | * @param {number[]} arr2 4 | * @return {number[]} 5 | */ 6 | const relativeSortArray = function(arr1, arr2) { 7 | const res = []; 8 | arr2.forEach(item => { 9 | const temp = arr1.filter(v => v === item); 10 | arr1 = arr1.filter(v => v !== item); 11 | if (temp.length) { 12 | res.push(...temp); 13 | } 14 | }); 15 | 16 | return res.concat(arr1.sort((a, b) => a - b)); 17 | }; 18 | -------------------------------------------------------------------------------- /src/5.linked-list/9.反转链表.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for singly-linked list. 3 | * function ListNode(val) { 4 | * this.val = val; 5 | * this.next = null; 6 | * } 7 | */ 8 | /** 9 | * @param {ListNode} head 10 | * @return {ListNode} 11 | */ 12 | const reverseList = function(head) { 13 | let prev = null; 14 | let cur = head; 15 | while (cur) { 16 | const next = cur.next; 17 | cur.next = prev; 18 | prev = cur; 19 | cur = next; 20 | } 21 | return prev; 22 | }; 23 | -------------------------------------------------------------------------------- /src/lodash/range.js: -------------------------------------------------------------------------------- 1 | const _ = require('lodash'); 2 | console.log(_.range(4)); 3 | console.log(_.range(-4)); 4 | console.log(_.range(1, 5)); 5 | console.log(_.range(0, 20, 5)); 6 | 7 | // native 8 | const _range = (start, end, step) => { 9 | console.log(Array.from({ length: 4 }, (_, i) => i)); 10 | console.log(Array.from({ length: 4 }, (_, i) => -i)); 11 | console.log(Array.from({ length: 4 }, (_, i) => i + 1)); 12 | console.log(Array.from({ length: 4 }, (_, i) => i * 5)); 13 | }; 14 | 15 | _range(); 16 | -------------------------------------------------------------------------------- /src/1.stack/4.最近的请求次数.js: -------------------------------------------------------------------------------- 1 | const RecentCounter = function() { 2 | this.stack = []; 3 | }; 4 | 5 | /** 6 | * @param {number} t 7 | * @return {number} 8 | */ 9 | RecentCounter.prototype.ping = function(t) { 10 | this.stack.push(t); 11 | while (this.stack[0] < t - 3000) { 12 | this.stack.shift(); 13 | } 14 | return this.stack.length; 15 | }; 16 | 17 | /** 18 | * Your RecentCounter object will be instantiated and called as such: 19 | * var obj = new RecentCounter() 20 | * var param_1 = obj.ping(t) 21 | */ 22 | -------------------------------------------------------------------------------- /src/2.queue/1.最近的请求次数.js: -------------------------------------------------------------------------------- 1 | const RecentCounter = function() { 2 | this.stack = []; 3 | }; 4 | 5 | /** 6 | * @param {number} t 7 | * @return {number} 8 | */ 9 | RecentCounter.prototype.ping = function(t) { 10 | this.stack.push(t); 11 | while (this.stack[0] < t - 3000) { 12 | this.stack.shift(); 13 | } 14 | return this.stack.length; 15 | }; 16 | 17 | /** 18 | * Your RecentCounter object will be instantiated and called as such: 19 | * var obj = new RecentCounter() 20 | * var param_1 = obj.ping(t) 21 | */ 22 | -------------------------------------------------------------------------------- /src/5.linked-list/17.二进制链表转整数.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for singly-linked list. 3 | * function ListNode(val, next) { 4 | * this.val = (val===undefined ? 0 : val) 5 | * this.next = (next===undefined ? null : next) 6 | * } 7 | */ 8 | /** 9 | * @param {ListNode} head 10 | * @return {number} 11 | */ 12 | const getDecimalValue = function(head) { 13 | let cur = head; 14 | let num = ''; 15 | while (cur) { 16 | num += cur.val; 17 | cur = cur.next; 18 | } 19 | return parseInt(num, 2); 20 | }; 21 | -------------------------------------------------------------------------------- /src/4.array/33.存在重复元素 II.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[]} nums 3 | * @param {number} k 4 | * @return {boolean} 5 | */ 6 | const containsNearbyDuplicate = function(nums, k) { 7 | const map = new Map(); 8 | for (let i = 0; i < nums.length; i++) { 9 | const cur = map.get(nums[i]); 10 | if (cur && cur.value === nums[i]) { 11 | if (Math.abs(cur.index - i) <= k) { 12 | return true; 13 | } 14 | } 15 | map.set(nums[i], { index: i, value: nums[i] }); 16 | } 17 | return false; 18 | }; 19 | -------------------------------------------------------------------------------- /src/6.binary-tree/11.二叉树的镜像.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for a binary tree node. 3 | * function TreeNode(val) { 4 | * this.val = val; 5 | * this.left = this.right = null; 6 | * } 7 | */ 8 | /** 9 | * @param {TreeNode} root 10 | * @return {TreeNode} 11 | */ 12 | const mirrorTree = function(root) { 13 | if (!root) { 14 | return null; 15 | } 16 | const left = mirrorTree(root.left); 17 | const right = mirrorTree(root.right); 18 | root.left = right; 19 | root.right = left; 20 | return root; 21 | }; 22 | -------------------------------------------------------------------------------- /src/1.stack/8.文件夹操作日志搜索器.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {string[]} logs 3 | * @return {number} 4 | */ 5 | const minOperations = function(logs) { 6 | let res = 0; 7 | for (const v of logs) { 8 | switch (v) { 9 | case './': 10 | res += 0; 11 | break; 12 | case '../': 13 | if (res) { 14 | res += -1; 15 | } else { 16 | res = 0; 17 | } 18 | break; 19 | default: 20 | res += 1; 21 | break; 22 | } 23 | } 24 | return res; 25 | }; 26 | -------------------------------------------------------------------------------- /src/3.string/4.实现strStr().js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {string} haystack 3 | * @param {string} needle 4 | * @return {number} 5 | */ 6 | const strStr = function(haystack, needle) { 7 | if (needle === '') { 8 | return 0; 9 | } 10 | if (haystack.length < needle.length) { 11 | return -1; 12 | } 13 | const targetLength = needle.length; 14 | for (let i = 0; i <= haystack.length - targetLength; i++) { 15 | if (needle === haystack.substr(i, targetLength)) { 16 | return i; 17 | } 18 | } 19 | return -1; 20 | }; 21 | -------------------------------------------------------------------------------- /src/6.binary-tree/25.N叉树的最大深度.js: -------------------------------------------------------------------------------- 1 | /** 2 | * // Definition for a Node. 3 | * function Node(val,children) { 4 | * this.val = val; 5 | * this.children = children; 6 | * }; 7 | */ 8 | 9 | /** 10 | * @param {Node|null} root 11 | * @return {number} 12 | */ 13 | const maxDepth = function(root) { 14 | if (!root) return 0; 15 | let num = 0; 16 | if (root.children) { 17 | root.children.forEach(v => { 18 | const n = maxDepth(v); 19 | num = Math.max(num, n); 20 | }); 21 | } 22 | return num + 1; 23 | }; 24 | 25 | -------------------------------------------------------------------------------- /src/3.string/13.字符串中唯一字符.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {string} s 3 | * @return {number} 4 | */ 5 | const firstUniqChar = function(s) { 6 | // for (let i = 0; i < s.length; i++) { 7 | // if (s.indexOf(s[i]) === s.lastIndexOf(s[i])) { 8 | // return i 9 | // } 10 | // } 11 | const map = {}; 12 | for (let i = 0; i < s.length; i++) { 13 | map[s[i]] = (map[s[i]] || 0) + 1; 14 | } 15 | for (let i = 0; i < s.length; i++) { 16 | if (map[s[i]] === 1) { 17 | return i; 18 | } 19 | } 20 | 21 | return -1; 22 | }; 23 | -------------------------------------------------------------------------------- /src/5.linked-list/1.翻转链表.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for singly-linked list. 3 | * function ListNode(val, next) { 4 | * this.val = (val===undefined ? 0 : val) 5 | * this.next = (next===undefined ? null : next) 6 | * } 7 | */ 8 | /** 9 | * @param {ListNode} head 10 | * @return {ListNode} 11 | */ 12 | const reverseList = function(head) { 13 | let prev = null; 14 | let cur = head; 15 | while (cur) { 16 | const next = cur.next; 17 | cur.next = prev; 18 | prev = cur; 19 | cur = next; 20 | } 21 | return prev; 22 | }; 23 | -------------------------------------------------------------------------------- /src/4.array/14.杨辉三角.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number} numRows 3 | * @return {number[][]} 4 | */ 5 | const generate = function(numRows) { 6 | const res = []; 7 | // 如果不是数组的首位和结尾,那么他当前的数据等于res[i - 1][j - 1] + res[i - 1][j] 8 | for (let i = 0; i < numRows; i++) { 9 | const subArr = []; 10 | for (let j = 0; j <= i; j++) { 11 | if (j > 0 && j < i) { 12 | subArr.push(res[i - 1][j - 1] + res[i - 1][j]); 13 | } else { 14 | subArr.push(1); 15 | } 16 | } 17 | res.push(subArr); 18 | } 19 | return res; 20 | }; 21 | -------------------------------------------------------------------------------- /src/4.array/29.按奇偶排序数组 II.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[]} nums 3 | * @return {number[]} 4 | */ 5 | const sortArrayByParityII = function(nums) { 6 | const odd = []; 7 | const even = []; 8 | const res = []; 9 | nums.forEach(v => { 10 | if (v % 2 === 0) { 11 | even.push(v); 12 | } else { 13 | odd.push(v); 14 | } 15 | }); 16 | for (let i = 0; i < nums.length; i++) { 17 | if (i % 2 === 0) { 18 | res.push(even.pop()); 19 | } else { 20 | res.push(odd.pop()); 21 | } 22 | } 23 | return res; 24 | }; 25 | -------------------------------------------------------------------------------- /src/7.hash-table/3.只出现一次的数字.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[]} nums 3 | * @return {number} 4 | */ 5 | const singleNumber = function(nums) { 6 | // const map = new Map(); 7 | // for (const v of nums) { 8 | // if (map.has(v)) { 9 | // map.set(v, 2); 10 | // } else { 11 | // map.set(v, 1); 12 | // } 13 | // } 14 | // for (const [ key, v ] of map.entries()) { 15 | // if (v === 1) { 16 | // return key; 17 | // } 18 | // } 19 | let ans = 0; 20 | for (const num of nums) { 21 | ans ^= num; 22 | } 23 | return ans; 24 | }; 25 | -------------------------------------------------------------------------------- /src/Promise/generator.js: -------------------------------------------------------------------------------- 1 | function ajax(url) { 2 | 3 | } 4 | 5 | function *main() { 6 | try { 7 | const res = yield ajax('/'); 8 | console.log(res); 9 | } catch (error) { 10 | console.log(error); 11 | } 12 | } 13 | 14 | function co(generator) { 15 | const g = generator(); 16 | 17 | function handleResult(result) { 18 | if (result.done) return; 19 | result.value.then(data => { 20 | handleResult(g.next(data)); 21 | }, error => { 22 | g.throw(error); 23 | }); 24 | } 25 | handleResult(g.next()); 26 | } 27 | 28 | co(main); 29 | -------------------------------------------------------------------------------- /src/5.linked-list/15.返回倒数第 k 个节点.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for singly-linked list. 3 | * function ListNode(val) { 4 | * this.val = val; 5 | * this.next = null; 6 | * } 7 | */ 8 | /** 9 | * @param {ListNode} head 10 | * @param {number} k 11 | * @return {number} 12 | */ 13 | const kthToLast = function(head, k) { 14 | // 快慢指针 15 | let fast = head; 16 | let slow = head; 17 | let index = 0; 18 | while (fast) { 19 | if (index >= k) { 20 | slow = slow.next; 21 | } 22 | fast = fast.next; 23 | index++; 24 | } 25 | return slow.val; 26 | }; 27 | -------------------------------------------------------------------------------- /src/4.array/13.多数元素.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[]} nums 3 | * @return {number} 4 | */ 5 | const majorityElement = function(nums) { 6 | const len = nums.length / 2; 7 | const map = new Map(); 8 | for (let i = 0; i < nums.length; i++) { 9 | const cur = nums[i]; 10 | const curLen = map.get(cur); 11 | if (curLen) { 12 | map.set(cur, curLen + 1); 13 | if (map.get(cur) > len) { 14 | return cur; 15 | } 16 | } else { 17 | map.set(cur, 1); 18 | if (map.get(cur) > len) { 19 | return cur; 20 | } 21 | } 22 | } 23 | }; 24 | -------------------------------------------------------------------------------- /src/5.linked-list/10.删除排序链表中的重复元素.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for singly-linked list. 3 | * function ListNode(val, next) { 4 | * this.val = (val===undefined ? 0 : val) 5 | * this.next = (next===undefined ? null : next) 6 | * } 7 | */ 8 | /** 9 | * @param {ListNode} head 10 | * @return {ListNode} 11 | */ 12 | const deleteDuplicates = function(head) { 13 | let cur = head; 14 | while (cur && cur.next) { 15 | if (cur.val === cur.next.val) { 16 | cur.next = cur.next.next; 17 | continue; 18 | } 19 | cur = cur.next; 20 | } 21 | return head; 22 | }; 23 | -------------------------------------------------------------------------------- /src/1.stack/15.比较含退格的字符串.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {string} s 3 | * @param {string} t 4 | * @return {boolean} 5 | */ 6 | const backspaceCompare = function(s, t) { 7 | const stackS = []; 8 | const stackT = []; 9 | for (let i = 0; i < s.length; i++) { 10 | if (s[i] === '#') { 11 | stackS.pop(); 12 | } else { 13 | stackS.push(s[i]); 14 | } 15 | } 16 | for (let i = 0; i < t.length; i++) { 17 | if (t[i] === '#') { 18 | stackT.pop(); 19 | } else { 20 | stackT.push(t[i]); 21 | } 22 | } 23 | 24 | return stackS.join() === stackT.join(); 25 | }; 26 | -------------------------------------------------------------------------------- /src/5.linked-list/20.回文链表.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for singly-linked list. 3 | * function ListNode(val) { 4 | * this.val = val; 5 | * this.next = null; 6 | * } 7 | */ 8 | /** 9 | * @param {ListNode} head 10 | * @return {boolean} 11 | */ 12 | const isPalindrome = function(head) { 13 | const list = []; 14 | let cur = head; 15 | while (cur) { 16 | list.push(cur.val); 17 | cur = cur.next; 18 | } 19 | 20 | for (let i = 0, j = list.length - 1; i < j; i++, j--) { 21 | if (list[i] !== list[j]) { 22 | return false; 23 | } 24 | } 25 | return true; 26 | }; 27 | -------------------------------------------------------------------------------- /src/6.binary-tree/1.二叉树的最大深度.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for a binary tree node. 3 | * function TreeNode(val, left, right) { 4 | * this.val = (val===undefined ? 0 : val) 5 | * this.left = (left===undefined ? null : left) 6 | * this.right = (right===undefined ? null : right) 7 | * } 8 | */ 9 | /** 10 | * @param {TreeNode} root 11 | * @return {number} 12 | */ 13 | const maxDepth = function(root) { 14 | if (root == null) { 15 | return 0; 16 | } 17 | const left = maxDepth(root.left); 18 | const right = maxDepth(root.right); 19 | return Math.max(left, right) + 1; 20 | }; 21 | -------------------------------------------------------------------------------- /src/4.array/26.杨辉三角2.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number} rowIndex 3 | * @return {number[]} 4 | */ 5 | const getRow = function(rowIndex) { 6 | if (rowIndex === 0) return [ 1 ]; 7 | const res = []; 8 | // 如果不是数组的首位和结尾,那么他当前的数据等于res[i - 1][j - 1] + res[i - 1][j] 9 | for (let i = 0; i <= rowIndex; i++) { 10 | const subArr = []; 11 | for (let j = 0; j <= i; j++) { 12 | if (j > 0 && j < i) { 13 | subArr.push(res[i - 1][j - 1] + res[i - 1][j]); 14 | } else { 15 | subArr.push(1); 16 | } 17 | } 18 | res.push(subArr); 19 | } 20 | return res[res.length - 1]; 21 | }; 22 | -------------------------------------------------------------------------------- /src/5.linked-list/12.删除链表的节点.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for singly-linked list. 3 | * function ListNode(val) { 4 | * this.val = val; 5 | * this.next = null; 6 | * } 7 | */ 8 | /** 9 | * @param {ListNode} head 10 | * @param {number} val 11 | * @return {ListNode} 12 | */ 13 | const deleteNode = function(head, val) { 14 | if (head.val === val) { 15 | return head.next; 16 | } 17 | let cur = head; 18 | while (cur.next) { 19 | if (cur.next.val === val) { 20 | cur.next = cur.next.next; 21 | return head; 22 | } 23 | cur = cur.next; 24 | } 25 | return head; 26 | }; 27 | -------------------------------------------------------------------------------- /src/4.array/23.拼写单词.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {string[]} words 3 | * @param {string} chars 4 | * @return {number} 5 | */ 6 | const countCharacters = function(words, chars) { 7 | let res = 0; 8 | for (let i = 0; i < words.length; i++) { 9 | const s = words[i]; 10 | let c = chars, 11 | flag = true, 12 | j = 0; 13 | while (j < s.length) { 14 | if (c.indexOf(s[j]) === -1) { 15 | flag = false; 16 | break; 17 | } 18 | c = c.replace(s[j], ''); 19 | j++; 20 | } 21 | if (flag) { 22 | res += s.length; 23 | } 24 | } 25 | return res; 26 | }; 27 | -------------------------------------------------------------------------------- /src/5.linked-list/8.相交链表.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for singly-linked list. 3 | * function ListNode(val) { 4 | * this.val = val; 5 | * this.next = null; 6 | * } 7 | */ 8 | 9 | /** 10 | * @param {ListNode} headA 11 | * @param {ListNode} headB 12 | * @return {ListNode} 13 | */ 14 | const getIntersectionNode = function(headA, headB) { 15 | const set = new Set(); 16 | while (headA) { 17 | set.add(headA); 18 | headA = headA.next; 19 | } 20 | while (headB) { 21 | if (set.has(headB)) { 22 | return headB; 23 | } 24 | headB = headB.next; 25 | } 26 | return null; 27 | }; 28 | -------------------------------------------------------------------------------- /src/5.linked-list/21.链表相交.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for singly-linked list. 3 | * function ListNode(val) { 4 | * this.val = val; 5 | * this.next = null; 6 | * } 7 | */ 8 | 9 | /** 10 | * @param {ListNode} headA 11 | * @param {ListNode} headB 12 | * @return {ListNode} 13 | */ 14 | const getIntersectionNode = function(headA, headB) { 15 | const set = new Set(); 16 | while (headA) { 17 | set.add(headA); 18 | headA = headA.next; 19 | } 20 | 21 | while (headB) { 22 | if (set.has(headB)) { 23 | return headB; 24 | } 25 | headB = headB.next; 26 | } 27 | return null; 28 | }; 29 | -------------------------------------------------------------------------------- /src/3.string/2.最长公共前缀.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {string[]} strs 3 | * @return {string} 4 | */ 5 | const longestCommonPrefix = function(strs) { 6 | let res = ''; 7 | let maxPrefixLength = 200; 8 | strs.forEach(v => { 9 | if (v.length < maxPrefixLength) { 10 | maxPrefixLength = v.length; 11 | } 12 | }); 13 | 14 | for (let i = 0; i < maxPrefixLength; i++) { 15 | const set = new Set(); 16 | strs.forEach(v => { 17 | set.add(v[i] || ''); 18 | }); 19 | if (set.size === 1) { 20 | res += [ ...set ][0]; 21 | } else { 22 | return res; 23 | } 24 | } 25 | return res; 26 | }; 27 | -------------------------------------------------------------------------------- /src/5.linked-list/18.两个链表的第一个公共节点.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for singly-linked list. 3 | * function ListNode(val) { 4 | * this.val = val; 5 | * this.next = null; 6 | * } 7 | */ 8 | 9 | /** 10 | * @param {ListNode} headA 11 | * @param {ListNode} headB 12 | * @return {ListNode} 13 | */ 14 | const getIntersectionNode = function(headA, headB) { 15 | const set = new Set(); 16 | while (headA) { 17 | set.add(headA); 18 | headA = headA.next; 19 | } 20 | 21 | while (headB) { 22 | if (set.has(headB)) { 23 | return headB; 24 | } 25 | headB = headB.next; 26 | } 27 | return null; 28 | }; 29 | -------------------------------------------------------------------------------- /src/6.binary-tree/16.二叉搜索树的第k大节点.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for a binary tree node. 3 | * function TreeNode(val) { 4 | * this.val = val; 5 | * this.left = this.right = null; 6 | * } 7 | */ 8 | /** 9 | * @param {TreeNode} root 10 | * @param {number} k 11 | * @return {number} 12 | */ 13 | const kthLargest = function(root, k) { 14 | const set = new Set(); 15 | const dfs = root => { 16 | if (root === null) return; 17 | set.add(root.val); 18 | dfs(root.left); 19 | dfs(root.right); 20 | }; 21 | dfs(root); 22 | const res = [ ...set ].sort((a, b) => a - b); 23 | return res[res.length - k]; 24 | }; 25 | -------------------------------------------------------------------------------- /src/1.stack/7.棒球比赛.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {string[]} ops 3 | * @return {number} 4 | */ 5 | const calPoints = function(ops) { 6 | const stack = []; 7 | for (let i = 0; i < ops.length; i++) { 8 | switch (ops[i]) { 9 | case 'C': 10 | stack.pop(); 11 | break; 12 | case 'D': 13 | stack.push(stack[stack.length - 1] * 2); 14 | break; 15 | case '+': 16 | stack.push(+stack[stack.length - 1] + +stack[stack.length - 2]); 17 | break; 18 | default: 19 | stack.push(+ops[i]); 20 | } 21 | } 22 | return stack.reduce((prev, next) => prev + next, 0); 23 | }; 24 | -------------------------------------------------------------------------------- /src/3.string/3.罗马数字转整数.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {string} s 3 | * @return {number} 4 | */ 5 | const romanToInt = function(s) { 6 | const map = { 7 | I: 1, 8 | V: 5, 9 | X: 10, 10 | L: 50, 11 | C: 100, 12 | D: 500, 13 | M: 1000, 14 | }; 15 | let sum = 0; 16 | for (let i = 0; i < s.length; i++) { 17 | let prev = map[s[i]]; 18 | const next = map[s[i + 1]]; 19 | console.log('prev', prev); 20 | console.log('next', next); 21 | // 如果前一个值小于后一个值 那么后一个减去前一个 22 | if (prev < next) { 23 | prev = next - prev; 24 | i++; 25 | } 26 | sum += prev; 27 | } 28 | return sum; 29 | }; 30 | -------------------------------------------------------------------------------- /src/6.binary-tree/27.二叉搜索树的最近公共祖先.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for a binary tree node. 3 | * function TreeNode(val) { 4 | * this.val = val; 5 | * this.left = this.right = null; 6 | * } 7 | */ 8 | /** 9 | * @param {TreeNode} root 10 | * @param {TreeNode} p 11 | * @param {TreeNode} q 12 | * @return {TreeNode} 13 | */ 14 | const lowestCommonAncestor = function(root, p, q) { 15 | if (p.val < root.val && q.val < root.val) { 16 | return lowestCommonAncestor(root.left, p, q); 17 | } 18 | if (p.val > root.val && q.val > root.val) { 19 | return lowestCommonAncestor(root.right, p, q); 20 | } 21 | return root; 22 | }; 23 | -------------------------------------------------------------------------------- /src/5.linked-list/16.移除重复节点.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for singly-linked list. 3 | * function ListNode(val) { 4 | * this.val = val; 5 | * this.next = null; 6 | * } 7 | */ 8 | /** 9 | * @param {ListNode} head 10 | * @return {ListNode} 11 | */ 12 | const removeDuplicateNodes = function(head) { 13 | if (!head) return null; 14 | const set = new Set(); 15 | set.add(head.val); 16 | 17 | let cur = head; 18 | while (cur.next) { 19 | if (set.has(cur.next.val)) { 20 | cur.next = cur.next.next; 21 | } else { 22 | set.add(cur.next.val); 23 | cur = cur.next; 24 | } 25 | } 26 | return head; 27 | }; 28 | -------------------------------------------------------------------------------- /src/4.array/20.将数组分成和相等的三个部分.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[]} arr 3 | * @return {boolean} 4 | */ 5 | const canThreePartsEqualSum = function(arr) { 6 | const sumA = arr.reduce((prev, next) => prev + next, 0); 7 | // 总和如果不能被3整除那么返回false 8 | if (sumA % 3 !== 0) return false; 9 | const part = sumA / 3; 10 | let groupCount = 0; 11 | let currentSum = 0; 12 | for (let i = 0; i < arr.length; i++) { 13 | currentSum += arr[i]; 14 | if (currentSum === part) { 15 | groupCount++; 16 | currentSum = 0; 17 | } 18 | if (groupCount === 3) { 19 | return true; 20 | } 21 | } 22 | return groupCount === 3; 23 | }; 24 | -------------------------------------------------------------------------------- /src/5.linked-list/4.回文链表.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for singly-linked list. 3 | * function ListNode(val, next) { 4 | * this.val = (val===undefined ? 0 : val) 5 | * this.next = (next===undefined ? null : next) 6 | * } 7 | */ 8 | /** 9 | * @param {ListNode} head 10 | * @return {boolean} 11 | */ 12 | const isPalindrome = function(head) { 13 | const list = []; 14 | while (head) { 15 | list.push(head.val); 16 | head = head.next; 17 | } 18 | const len = list.length; 19 | for (let i = 0, j = len - 1; i < j; i++, j--) { 20 | if (list[i] !== list[j]) { 21 | return false; 22 | } 23 | } 24 | return true; 25 | }; 26 | -------------------------------------------------------------------------------- /src/6.binary-tree/19.平衡二叉树.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for a binary tree node. 3 | * function TreeNode(val) { 4 | * this.val = val; 5 | * this.left = this.right = null; 6 | * } 7 | */ 8 | /** 9 | * @param {TreeNode} root 10 | * @return {boolean} 11 | */ 12 | const isBalanced = function(root) { 13 | // 获取当前节点高度 14 | function getH(root) { 15 | if (!root) return 0; 16 | return Math.max(getH(root.left), getH(root.right)) + 1; 17 | } 18 | if (!root) return true; 19 | return ( 20 | Math.abs(getH(root.left) - getH(root.right)) <= 1 && 21 | isBalanced(root.left) && 22 | isBalanced(root.right) 23 | ); 24 | }; 25 | -------------------------------------------------------------------------------- /src/6.binary-tree/18.对称的二叉树.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for a binary tree node. 3 | * function TreeNode(val) { 4 | * this.val = val; 5 | * this.left = this.right = null; 6 | * } 7 | */ 8 | /** 9 | * @param {TreeNode} root 10 | * @return {boolean} 11 | */ 12 | const isSymmetric = function(root) { 13 | if (!root) return true; 14 | function isEqual(left, right) { 15 | if (!left && !right) return true; 16 | if (!left || !right) return false; 17 | return left.val === right.val && 18 | isEqual(left.left, right.right) && 19 | isEqual(left.right, right.left); 20 | } 21 | return isEqual(root.left, root.right); 22 | }; 23 | -------------------------------------------------------------------------------- /src/5.linked-list/13.移出链表元素.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for singly-linked list. 3 | * function ListNode(val, next) { 4 | * this.val = (val===undefined ? 0 : val) 5 | * this.next = (next===undefined ? null : next) 6 | * } 7 | */ 8 | /** 9 | * @param {ListNode} head 10 | * @param {number} val 11 | * @return {ListNode} 12 | */ 13 | const removeElements = function(head, val) { 14 | const list = new ListNode(0); 15 | list.next = head; 16 | let temp = list; 17 | while (temp.next) { 18 | if (temp.next.val === val) { 19 | temp.next = temp.next.next; 20 | } else { 21 | temp = temp.next; 22 | } 23 | } 24 | return list.next; 25 | }; 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## 前端力扣刷题路线图(简单部分) 2 | 不积跬步无以至千里,许多人在学习算法的路上放弃,第一是因为起点太高,刚上来就做一些中等难度甚至困难的题,遇到挫折就很难坚持下去,就算刚开始从简单做起,也会在基础尚未牢固的情况下在中等难度下退缩;第二是因为没有路线图,在没有刷题规划的时候,就只能随缘打开任意一题开始了,同样很难坚持下来。 3 | 所以我特地把LeetCode上简单难度的题目根据数据结构进行分类,制定了一条无痛刷题路线图,相信这些简单题目能够让你得心应手,逐步培养算法题的自信心 4 | 5 | ## 题目大纲 6 | [路线图 · 语雀](https://www.yuque.com/docs/share/937cc72b-9389-449d-a154-b286a296ca80) 7 | ![](https://cdn.jsdelivr.net/gh/Orime112/picbed/img/20201228182455.png) 8 | 9 | ## 视频操作指引 10 | [前端小白力扣刷题工具及流程 11 | ](https://www.bilibili.com/video/BV1xX4y1T746) 12 | 13 | ## 调试方法 14 | - 调试:设置断点 + F5 15 | - 快速执行:安装`Code Runner`插件后,快捷键执行`Ctrl+Shift+N` 16 | ![](https://cdn.jsdelivr.net/gh/Orime112/picbed/img/20201228182334.png) 17 | -------------------------------------------------------------------------------- /src/6.binary-tree/5.翻转二叉树.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for a binary tree node. 3 | * function TreeNode(val, left, right) { 4 | * this.val = (val===undefined ? 0 : val) 5 | * this.left = (left===undefined ? null : left) 6 | * this.right = (right===undefined ? null : right) 7 | * } 8 | */ 9 | /** 10 | * @param {TreeNode} root 11 | * @return {TreeNode} 12 | */ 13 | const invertTree = function(root) { 14 | // 终止条件:当前节点为 null 时返回 15 | // 交换当前节点的左右节点,再递归的交换当前节点的左节点,递归的交换当前节点的右节点 16 | if (!root) return null; 17 | const left = invertTree(root.left); 18 | const right = invertTree(root.right); 19 | root.left = right; 20 | root.right = left; 21 | return root; 22 | }; 23 | -------------------------------------------------------------------------------- /src/1.stack/1.删除最外层的括号.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {string} S 3 | * @return {string} 4 | */ 5 | const removeOuterParentheses = function(s) { 6 | if (!s || s.length % 2 !== 0) { 7 | return false; 8 | } 9 | let stack = []; 10 | let res = ''; 11 | for (const v of s) { 12 | switch (v) { 13 | case '(': 14 | if (stack.push(v) > 1) { 15 | res += '('; 16 | } 17 | break; 18 | case ')': 19 | if (stack.length > 1) { 20 | res += ')'; 21 | stack.pop(); 22 | } else { 23 | stack = []; 24 | } 25 | break; 26 | default: 27 | break; 28 | } 29 | } 30 | return res; 31 | }; 32 | -------------------------------------------------------------------------------- /src/4.array/15.两数之和.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[]} numbers 3 | * @param {number} target 4 | * @return {number[]} 5 | */ 6 | const twoSum = function(numbers, target) { 7 | // for (let i = 0; i < numbers.length; i++) { 8 | // const cur = numbers[i]; 9 | // for (let j = i + 1; j < numbers.length; j++) { 10 | // if (cur + numbers[j] === target) { 11 | // return [ i + 1, j + 1 ] 12 | // } 13 | // } 14 | // } 15 | const map = new Map(); 16 | for (let i = 0; i < numbers.length; i++) { 17 | if (map.has(target - numbers[i])) { 18 | return [ map.get(target - numbers[i]), i + 1 ]; 19 | } 20 | map.set(numbers[i], i + 1); 21 | 22 | } 23 | }; 24 | -------------------------------------------------------------------------------- /src/6.binary-tree/3.相同的树.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for a binary tree node. 3 | * function TreeNode(val, left, right) { 4 | * this.val = (val===undefined ? 0 : val) 5 | * this.left = (left===undefined ? null : left) 6 | * this.right = (right===undefined ? null : right) 7 | * } 8 | */ 9 | /** 10 | * @param {TreeNode} p 11 | * @param {TreeNode} q 12 | * @return {boolean} 13 | */ 14 | const isSameTree = function(p, q) { 15 | // 如果两个树都为空 返回 true 16 | // 如果 一个树为空 一个树不为空 返回fasle 17 | // 如果不为空 就判断他们的子节点是否相同 18 | if (!p && !q) return true; 19 | if (!p || !q) return false; 20 | if (p.val !== q.val) return false; 21 | return isSameTree(p.left, q.left) && isSameTree(p.right, q.right); 22 | }; 23 | -------------------------------------------------------------------------------- /src/6.binary-tree/12.合并二叉树.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for a binary tree node. 3 | * function TreeNode(val, left, right) { 4 | * this.val = (val===undefined ? 0 : val) 5 | * this.left = (left===undefined ? null : left) 6 | * this.right = (right===undefined ? null : right) 7 | * } 8 | */ 9 | /** 10 | * @param {TreeNode} root1 11 | * @param {TreeNode} root2 12 | * @return {TreeNode} 13 | */ 14 | const mergeTrees = function(root1, root2) { 15 | // 终止条件 16 | if (!root1) return root2; 17 | if (!root2) return root1; 18 | root1.val = root1.val + root2.val; 19 | 20 | root1.left = mergeTrees(root1.left, root2.left); 21 | root1.right = mergeTrees(root1.right, root2.right); 22 | return root1; 23 | }; 24 | -------------------------------------------------------------------------------- /src/6.binary-tree/26.N 叉树的前序遍历.js: -------------------------------------------------------------------------------- 1 | /** 2 | * // Definition for a Node. 3 | * function Node(val, children) { 4 | * this.val = val; 5 | * this.children = children; 6 | * }; 7 | */ 8 | 9 | /** 10 | * @param {Node|null} root 11 | * @return {number[]} 12 | */ 13 | const preorder = function(root) { 14 | if (!root) return []; 15 | const res = []; 16 | // 根节点入栈 17 | const stack = [ root ]; 18 | // 栈还有值的时候 19 | while (stack.length) { 20 | // 栈顶元素出栈 21 | const n = stack.pop(); 22 | // 将栈顶元素推入res队列 23 | res.push(n.val); 24 | let len = n.children.length; 25 | // 如果栈顶元素有子树,子树从右开始,依次推入栈 26 | while (len--) { 27 | stack.push(n.children[len]); 28 | } 29 | } 30 | return res; 31 | }; 32 | -------------------------------------------------------------------------------- /src/lodash/debounce.js: -------------------------------------------------------------------------------- 1 | // 防抖 2 | function debounce(fn, delay) { 3 | let timer; 4 | return function(...args) { 5 | const ctx = this; 6 | if (timer) clearTimeout(timer); 7 | timer = setTimeout(function() { 8 | fn.apply(ctx, args); 9 | }, delay); 10 | }; 11 | } 12 | 13 | 14 | function debounce1(fn, delay) { 15 | let timer = null; 16 | return (...args) => { 17 | if (timer) clearTimeout(timer); 18 | timer = setTimeout(() => fn(...args), delay); 19 | }; 20 | } 21 | 22 | 23 | function debounce2(fn, delay) { 24 | let timer = null; 25 | return (...args) => { 26 | if (timer) clearTimeout(timer); 27 | timer = setTimeout(() => { 28 | fn(...args); 29 | }, delay); 30 | }; 31 | } 32 | -------------------------------------------------------------------------------- /src/5.linked-list/3.环形链表.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for singly-linked list. 3 | * function ListNode(val) { 4 | * this.val = val; 5 | * this.next = null; 6 | * } 7 | */ 8 | 9 | /** 10 | * @param {ListNode} head 11 | * @return {boolean} 12 | */ 13 | const hasCycle = function(head) { 14 | // 污链法 15 | // while(head) { 16 | // if (head.tag) { 17 | // return true; 18 | // } 19 | // head.tag = true; 20 | // head = head.next; 21 | // } 22 | // 快慢指针 23 | let slow = head; 24 | let fast = head; 25 | while (fast && fast.next) { 26 | slow = slow.next; 27 | fast = fast.next.next; 28 | if (slow === fast) { 29 | return true; 30 | } 31 | } 32 | return false; 33 | }; 34 | -------------------------------------------------------------------------------- /src/1.stack/3.有效的括号.js: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * @param {string} s 4 | * @return {boolean} 5 | */ 6 | const isValid = function(s) { 7 | if (!s || s.length % 2 !== 0) { 8 | return false; 9 | } 10 | const stack = []; 11 | for (const v of s) { 12 | switch (v) { 13 | case '(': 14 | case '[': 15 | case '{': 16 | stack.push(v); 17 | break; 18 | case ')': 19 | if (stack.pop() !== '(') return false; 20 | break; 21 | case ']': 22 | if (stack.pop() !== '[') return false; 23 | break; 24 | case '}': 25 | if (stack.pop() !== '{') return false; 26 | break; 27 | default: 28 | break; 29 | } 30 | } 31 | return !stack.length; 32 | }; 33 | -------------------------------------------------------------------------------- /src/3.string/1.有效括号.js: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * @param {string} s 4 | * @return {boolean} 5 | */ 6 | const isValid = function(s) { 7 | if (!s || s.length % 2 !== 0) { 8 | return false; 9 | } 10 | const stack = []; 11 | for (const v of s) { 12 | switch (v) { 13 | case '(': 14 | case '[': 15 | case '{': 16 | stack.push(v); 17 | break; 18 | case ')': 19 | if (stack.pop() !== '(') return false; 20 | break; 21 | case ']': 22 | if (stack.pop() !== '[') return false; 23 | break; 24 | case '}': 25 | if (stack.pop() !== '{') return false; 26 | break; 27 | default: 28 | break; 29 | } 30 | } 31 | return !stack.length; 32 | }; 33 | -------------------------------------------------------------------------------- /src/6.binary-tree/24.二叉树的最近公共祖先.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for a binary tree node. 3 | * function TreeNode(val) { 4 | * this.val = val; 5 | * this.left = this.right = null; 6 | * } 7 | */ 8 | /** 9 | * @param {TreeNode} root 10 | * @param {TreeNode} p 11 | * @param {TreeNode} q 12 | * @return {TreeNode} 13 | */ 14 | const lowestCommonAncestor = function(root, p, q) { 15 | if (!root || root.val === p.val || root.val === q.val) return root; 16 | const left = lowestCommonAncestor(root.left, p, q); 17 | const right = lowestCommonAncestor(root.right, p, q); 18 | // 左子树找不到,返回右子树 19 | if (!left) return right; 20 | // 右子树找不到,返回左子树 21 | if (!right) return left; 22 | // 左右子树都找到了,那么root就是要找的 23 | return root; 24 | }; 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /src/lodash/throttle.js: -------------------------------------------------------------------------------- 1 | function throttle(fn, delay) { 2 | let lastTime = 0; 3 | return function(...args) { 4 | const nowTime = +new Date(); 5 | if (nowTime - lastTime > delay) { 6 | fn(args); 7 | lastTime = nowTime; 8 | } 9 | }; 10 | } 11 | 12 | function throttle1(fn, delay) { 13 | let prevTime = 0; 14 | return (...args) => { 15 | const nowTime = +new Date(); 16 | if (nowTime - prevTime > delay) { 17 | fn(...args); 18 | prevTime = nowTime; 19 | } 20 | }; 21 | } 22 | 23 | function throttle2(fn, delay) { 24 | let lastTime = 0; 25 | return (...args) => { 26 | const nowTime = +new Date(); 27 | if (nowTime - lastTime < delay) return; 28 | fn(...args); 29 | lastTime = nowTime; 30 | }; 31 | } 32 | -------------------------------------------------------------------------------- /src/6.binary-tree/6.路径总和.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for a binary tree node. 3 | * function TreeNode(val, left, right) { 4 | * this.val = (val===undefined ? 0 : val) 5 | * this.left = (left===undefined ? null : left) 6 | * this.right = (right===undefined ? null : right) 7 | * } 8 | */ 9 | /** 10 | * @param {TreeNode} root 11 | * @param {number} targetSum 12 | * @return {boolean} 13 | */ 14 | const hasPathSum = function(root, targetSum) { 15 | if (!root) { 16 | return false; 17 | } 18 | // 递归遍历树的左右两侧,如果都为null的时候 判断targetSum和当前节点的值是否相等,如果相等就返回 19 | if (!root.left && !root.right) { 20 | return root.val === targetSum; 21 | } 22 | return hasPathSum(root.left, targetSum - root.val) || hasPathSum(root.right, targetSum - root.val); 23 | }; 24 | -------------------------------------------------------------------------------- /src/6.binary-tree/9.二叉树的直径.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for a binary tree node. 3 | * function TreeNode(val, left, right) { 4 | * this.val = (val===undefined ? 0 : val) 5 | * this.left = (left===undefined ? null : left) 6 | * this.right = (right===undefined ? null : right) 7 | * } 8 | */ 9 | /** 10 | * @param {TreeNode} root 11 | * @return {number} 12 | */ 13 | const diameterOfBinaryTree = function(root) { 14 | // 找出树高度 15 | // 返回最后最大的高度 16 | if (!root) return 0; 17 | const h = getH(root.left) + getH(root.right); 18 | return Math.max(h, diameterOfBinaryTree(root.left), diameterOfBinaryTree(root.right)); 19 | }; 20 | 21 | function getH(node) { 22 | if (node == null) return 0; 23 | return Math.max(getH(node.left), getH(node.right)) + 1; 24 | } 25 | -------------------------------------------------------------------------------- /src/6.binary-tree/17.从上到下打印二叉树 II.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for a binary tree node. 3 | * function TreeNode(val) { 4 | * this.val = val; 5 | * this.left = this.right = null; 6 | * } 7 | */ 8 | /** 9 | * @param {TreeNode} root 10 | * @return {number[][]} 11 | */ 12 | const levelOrder = function(root) { 13 | if (!root) return []; 14 | const queue = [ root ]; 15 | const res = []; // 结果 16 | let level = 0; 17 | while (queue.length) { 18 | res[level] = []; // 第几层遍历的结果 19 | 20 | let levelNum = queue.length; 21 | while (levelNum--) { 22 | const node = queue.shift(); 23 | res[level].push(node.val); 24 | if (node.left) queue.push(node.left); 25 | if (node.right) queue.push(node.right); 26 | } 27 | level++; 28 | } 29 | return res; 30 | }; 31 | -------------------------------------------------------------------------------- /src/lodash/compose.js: -------------------------------------------------------------------------------- 1 | 2 | // 模拟loadsh中的flowRight 3 | const flowRight = require('lodash').flowRight; 4 | 5 | const reverse = arr => arr.reverse(); 6 | const first = arr => arr[0]; 7 | const toUpper = s => s.toUpperCase(); 8 | 9 | // function compose(...args) { 10 | // return value => { 11 | // return args.reduceRight((prev, next) => next(prev), value); 12 | // }; 13 | // } 14 | 15 | const compose = (...args) => value => args.reduceRight((prev, next) => next(prev), value); 16 | 17 | const f = compose(toUpper, first, reverse); 18 | // const f = flowRight(toUpper, first, reverse); 19 | 20 | const res = f([ 'one', 'two', 'three' ]); 21 | console.log('res', res); 22 | 23 | const compose1 = args => { 24 | return value => { 25 | return args.reduceRight((prev, next) => next(prev), value); 26 | }; 27 | }; 28 | -------------------------------------------------------------------------------- /src/6.binary-tree/7.左叶子之和.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for a binary tree node. 3 | * function TreeNode(val, left, right) { 4 | * this.val = (val===undefined ? 0 : val) 5 | * this.left = (left===undefined ? null : left) 6 | * this.right = (right===undefined ? null : right) 7 | * } 8 | */ 9 | /** 10 | * @param {TreeNode} root 11 | * @return {number} 12 | */ 13 | const sumOfLeftLeaves = function(root) { 14 | let sum = 0; 15 | const arr = [ root ]; 16 | while (arr.length) { 17 | const { left, right } = arr.shift(); 18 | if (left) { 19 | // 左右都不存在,这就是叶子节点 20 | if (!left.left && !left.right) { 21 | sum += left.val; 22 | } else { 23 | arr.push(left); 24 | } 25 | } 26 | if (right) { 27 | arr.push(right); 28 | } 29 | } 30 | return sum; 31 | }; 32 | -------------------------------------------------------------------------------- /src/5.linked-list/7.链表的中间节点.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for singly-linked list. 3 | * function ListNode(val, next) { 4 | * this.val = (val===undefined ? 0 : val) 5 | * this.next = (next===undefined ? null : next) 6 | * } 7 | */ 8 | /** 9 | * @param {ListNode} head 10 | * @return {ListNode} 11 | */ 12 | const middleNode = function(head) { 13 | // let list = []; 14 | // while(head) { 15 | // list.push(head); 16 | // head = head.next; 17 | // } 18 | // let len = list.length; 19 | // let index = len % 2 === 0 ? len / 2 : (len - 1) / 2; 20 | // return list[index]; 21 | // 快慢指针,fast一次走两步 slow一次走一步 当fast到达结尾的时候 slow一定走了一半 22 | let fast = head; 23 | let slow = head; 24 | while (fast && fast.next) { 25 | fast = fast.next.next; 26 | slow = slow.next; 27 | } 28 | return slow; 29 | }; 30 | -------------------------------------------------------------------------------- /src/nativeJS/apply.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | global.a = 1; 3 | const obj = { a: 2 }; 4 | const fn = function(b, c) { console.log(this.a, b, c); return 1; }; 5 | fn(1, 2); 6 | fn.apply(obj, [ 1, 2 ]); 7 | 8 | Function.prototype._apply = function(base, args) { 9 | base = base || global; 10 | base.fn = this; 11 | const ret = base.fn(...args); 12 | delete base.fn; 13 | return ret; 14 | }; 15 | 16 | fn._apply(obj, [ 1, 2 ]); 17 | 18 | Function.prototype._apply1 = function(base, args) { 19 | base = base || window; 20 | base.fn = this; 21 | const ret = base.fn(...args); 22 | Reflect.deleteProperty(base, 'fn') 23 | return ret 24 | } 25 | 26 | 27 | Function.prototype.apply1 = function(ctx, args) { 28 | ctx = ctx || window 29 | ctx.fn = this 30 | const ret = ctx.fn(...args) 31 | delete ctx.fn 32 | return ret 33 | } -------------------------------------------------------------------------------- /src/nativeJS/call.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | global.a = 1; 3 | const obj = { a: 2 }; 4 | const fn = function(b,c) { console.log(this.a, b, c); return 1 } 5 | fn(1, 2) 6 | fn.call(obj, 1, 2) 7 | 8 | Function.prototype._call = function(base, ...args) { 9 | base = base || global; 10 | base.fn = this; 11 | const ret = base.fn(...args); 12 | delete base.fn; 13 | return ret; 14 | } 15 | 16 | fn._call(obj, 1, 2) 17 | 18 | 19 | Function.prototype._call1 = function(base, ...args) { 20 | base = base || global; 21 | base.fn = this; 22 | const ret = base.fn(...args); 23 | delete base.fn; 24 | return ret; 25 | } 26 | 27 | fn._call1(obj, 1, 2) 28 | 29 | 30 | Function.prototype.call1 = function(ctx, ...args) { 31 | ctx = ctx || window; 32 | ctx.fn = this; 33 | const ret = ctx.fn(...args); 34 | delete ctx.fn; 35 | return ret 36 | } -------------------------------------------------------------------------------- /src/lodash/memoized.js: -------------------------------------------------------------------------------- 1 | 2 | const request = url => Promise.resolve(); 3 | 4 | const cacheRequestFn = () => { 5 | const cache = {}; 6 | return (url, cb) => { 7 | cb(cache[url] ? cache[url] : (cache[url] = request(url))); 8 | }; 9 | }; 10 | 11 | const cacheRequest = cacheRequestFn(); 12 | 13 | 14 | const request1 = url => Promise.resolve(url); 15 | 16 | const cacheRequest1 = () => { 17 | const cache = Object.create(null); 18 | return (url, cb) => { 19 | cb(cache[url] ? cache[url] : (cache[url] = request1(url))); 20 | }; 21 | }; 22 | 23 | const request_2 = cacheRequest1(); 24 | 25 | request_2('/path', () => { 26 | console.log('test'); 27 | }); 28 | 29 | 30 | const request3 = () => { 31 | const cache = {}; 32 | return (url, cb) => { 33 | cb(cache[url] ? cache[url] : (cache[url] = request1(url))); 34 | }; 35 | }; 36 | -------------------------------------------------------------------------------- /src/1.stack/2.用两个栈实现队列.js: -------------------------------------------------------------------------------- 1 | // 这个题意真难懂~~~~~~~~~~ 左侧例子是代码执行步骤 2 | const CQueue = function() { 3 | this.stackA = []; 4 | this.stackB = []; 5 | }; 6 | 7 | /** 8 | * @param {number} value 9 | * @return {void} 10 | */ 11 | CQueue.prototype.appendTail = function(value) { 12 | this.stackA.push(value); 13 | }; 14 | 15 | /** 16 | * @return {number} 17 | */ 18 | CQueue.prototype.deleteHead = function() { 19 | if (this.stackB.length) { 20 | return this.stackB.pop(); 21 | } 22 | while (this.stackA.length) { 23 | this.stackB.push(this.stackA.pop()); 24 | } 25 | if (!this.stackB.length) { 26 | return -1; 27 | } 28 | return this.stackB.pop(); 29 | 30 | }; 31 | 32 | /** 33 | * Your CQueue object will be instantiated and called as such: 34 | * var obj = new CQueue() 35 | * obj.appendTail(value) 36 | * var param_2 = obj.deleteHead() 37 | */ 38 | -------------------------------------------------------------------------------- /src/6.binary-tree/22.二叉搜索树的最小绝对差.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for a binary tree node. 3 | * function TreeNode(val, left, right) { 4 | * this.val = (val===undefined ? 0 : val) 5 | * this.left = (left===undefined ? null : left) 6 | * this.right = (right===undefined ? null : right) 7 | * } 8 | */ 9 | /** 10 | * @param {TreeNode} root 11 | * @return {number} 12 | */ 13 | const getMinimumDifference = function(root) { 14 | const list = []; 15 | let num = Number.MAX_VALUE; 16 | const dfs = root => { 17 | if (!root) return; 18 | list.push(root.val); 19 | if (root.left) dfs(root.left); 20 | if (root.right) dfs(root.right); 21 | }; 22 | dfs(root); 23 | 24 | list.sort((a, b) => a - b); 25 | for (let i = 1; i < list.length; i++) { 26 | num = Math.min(num, list[i] - list[i - 1]); 27 | } 28 | return num; 29 | }; 30 | -------------------------------------------------------------------------------- /src/1.stack/17.滑动窗口最大的值.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[]} nums 3 | * @param {number} k 4 | * @return {number[]} 5 | */ 6 | const maxSlidingWindow = function(nums, k) { 7 | const res = []; 8 | if (!nums.length) { 9 | return res; 10 | } 11 | if (nums.length === k) { 12 | res.push(Math.max(...nums)); 13 | return res; 14 | } 15 | if (k <= 1) { 16 | return nums; 17 | } 18 | for (let i = 0; i < nums.length; i++) { 19 | const temp = nums.slice(i, k + i); 20 | if (temp.length < k) { 21 | return res; 22 | } 23 | res.push(Math.max(...temp)); 24 | 25 | } 26 | }; 27 | 28 | const maxSlidingWindow1 = function(nums, k) { 29 | if (k <= 1) return nums; 30 | const res = []; 31 | for (let i = 0; i < nums.length - k + 1; i++) { 32 | res.push(Math.max(...nums.slice(i, i + k))); 33 | } 34 | return res; 35 | }; 36 | -------------------------------------------------------------------------------- /src/2.queue/2.滑动窗口最大的值.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[]} nums 3 | * @param {number} k 4 | * @return {number[]} 5 | */ 6 | const maxSlidingWindow = function(nums, k) { 7 | const res = []; 8 | if (!nums.length) { 9 | return res; 10 | } 11 | if (nums.length === k) { 12 | res.push(Math.max(...nums)); 13 | return res; 14 | } 15 | if (k <= 1) { 16 | return nums; 17 | } 18 | for (let i = 0; i < nums.length; i++) { 19 | const temp = nums.slice(i, k + i); 20 | if (temp.length < k) { 21 | return res; 22 | } 23 | res.push(Math.max(...temp)); 24 | 25 | } 26 | }; 27 | 28 | const maxSlidingWindow1 = function(nums, k) { 29 | if (k <= 1) return nums; 30 | const res = []; 31 | for (let i = 0; i < nums.length - k + 1; i++) { 32 | res.push(Math.max(...nums.slice(i, i + k))); 33 | } 34 | return res; 35 | }; 36 | -------------------------------------------------------------------------------- /src/6.binary-tree/23.二叉搜索树中的众数.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for a binary tree node. 3 | * function TreeNode(val, left, right) { 4 | * this.val = (val===undefined ? 0 : val) 5 | * this.left = (left===undefined ? null : left) 6 | * this.right = (right===undefined ? null : right) 7 | * } 8 | */ 9 | /** 10 | * @param {TreeNode} root 11 | * @return {number[]} 12 | */ 13 | const findMode = function(root) { 14 | let res = {}, 15 | maxCount = 0, 16 | r = [], 17 | dfs = root => { 18 | res[root.val] = (res[root.val] || 0) + 1; 19 | if (res[root.val] >= maxCount) { 20 | res[root.val] > maxCount && (r.length = 0); 21 | maxCount = res[root.val]; 22 | r.push(root.val); 23 | } 24 | root.left && dfs(root.left) || root.right && dfs(root.right); 25 | }; 26 | return root && dfs(root) || r || []; 27 | }; 28 | -------------------------------------------------------------------------------- /src/6.binary-tree/28.二叉搜索树的范围和.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for a binary tree node. 3 | * function TreeNode(val, left, right) { 4 | * this.val = (val===undefined ? 0 : val) 5 | * this.left = (left===undefined ? null : left) 6 | * this.right = (right===undefined ? null : right) 7 | * } 8 | */ 9 | /** 10 | * @param {TreeNode} root 11 | * @param {number} low 12 | * @param {number} high 13 | * @return {number} 14 | */ 15 | const rangeSumBST = function(root, low, high) { 16 | // 递归出口 17 | if (!root) return 0; 18 | // 如果当前节点比hight大, 直接遍历左子树 19 | if (root.val > high) { 20 | return rangeSumBST(root.left, low, high); 21 | } 22 | // 如果当前节点比low小, 直接遍历右子树 23 | if (root.val < low) { 24 | return rangeSumBST(root.right, low, high); 25 | } 26 | return root.val + rangeSumBST(root.left, low, high) + rangeSumBST(root.right, low, high); 27 | }; 28 | -------------------------------------------------------------------------------- /src/6.binary-tree/7.平衡二叉树.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for a binary tree node. 3 | * function TreeNode(val, left, right) { 4 | * this.val = (val===undefined ? 0 : val) 5 | * this.left = (left===undefined ? null : left) 6 | * this.right = (right===undefined ? null : right) 7 | * } 8 | */ 9 | /** 10 | * @param {TreeNode} root 11 | * @return {boolean} 12 | */ 13 | const isBalanced = function(root) { 14 | // // 获取当前节点高度的递归函数 15 | const getH = root => { 16 | if (!root) return 0; 17 | // 返回左右节点的最大高度+1,(+1:根节点) 18 | return Math.max(getH(root.left), getH(root.right)) + 1; 19 | }; 20 | if (!root) return true; 21 | return ( 22 | // 根节点的左右高度差不大于1 23 | Math.abs(getH(root.left) - getH(root.right)) <= 1 && 24 | // 左子树是平衡二叉树 25 | isBalanced(root.left) && 26 | // 右字数是平衡二叉树 27 | isBalanced(root.right) 28 | ); 29 | }; 30 | -------------------------------------------------------------------------------- /src/5.linked-list/2.合并两个有序的链表.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for singly-linked list. 3 | * function ListNode(val, next) { 4 | * this.val = (val===undefined ? 0 : val) 5 | * this.next = (next===undefined ? null : next) 6 | * } 7 | */ 8 | /** 9 | * @param {ListNode} l1 10 | * @param {ListNode} l2 11 | * @return {ListNode} 12 | */ 13 | function ListNode(val, next) { 14 | this.val = (val === undefined ? 0 : val); 15 | this.next = (next === undefined ? null : next); 16 | } 17 | const mergeTwoLists = function(l1, l2) { 18 | const prevHead = new ListNode(-1); 19 | let prev = prevHead; 20 | while (l1 && l2) { 21 | if (l1.val <= l2.val) { 22 | prev.next = l1; 23 | l1 = l1.next; 24 | } else { 25 | prev.next = l2; 26 | l2 = l2.next; 27 | } 28 | prev = prev.next; 29 | } 30 | prev.next = l1 ? l1 : l2; 31 | return prevHead.next; 32 | }; 33 | -------------------------------------------------------------------------------- /src/6.binary-tree/10.将有序数组转换为二叉搜索树.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for a binary tree node. 3 | * function TreeNode(val, left, right) { 4 | * this.val = (val===undefined ? 0 : val) 5 | * this.left = (left===undefined ? null : left) 6 | * this.right = (right===undefined ? null : right) 7 | * } 8 | */ 9 | /** 10 | * @param {number[]} nums 11 | * @return {TreeNode} 12 | */ 13 | const sortedArrayToBST = function(nums) { 14 | // 当数组为奇数时比如 [0, 1, 2], 此时取中间数 1 为根节点, 0 和 2 分别为其左右子节点, 此时满足高度平衡的条件。 15 | // 当数组为偶数时比如 [0, 1], 此时取中间数 1 为根节点, 0 为其左右子节点, 此时满足高度平衡的条件。 16 | if (!nums.length) return null; 17 | const mid = Math.floor(nums.length / 2); 18 | const res = new TreeNode(nums[mid]); 19 | const left = nums.slice(0, mid); 20 | const right = nums.slice(mid + 1); 21 | res.left = sortedArrayToBST(left); 22 | res.right = sortedArrayToBST(right); 23 | return res; 24 | }; 25 | -------------------------------------------------------------------------------- /src/3.string/16.字符串相加.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {string} num1 3 | * @param {string} num2 4 | * @return {string} 5 | */ 6 | let ans = 0; 7 | let sum = []; 8 | const addStrings = function(num1, num2) { 9 | const num1Last = num1.slice(-1); 10 | const num2Last = num2.slice(-1); 11 | 12 | function add(a, b) { 13 | const sumNow = +a + +b + ans; 14 | ans = sumNow > 9 ? 1 : 0; 15 | // 按位与 取0 16 | return sumNow % 10 | 0; 17 | } 18 | 19 | sum.unshift(add(num1Last, num2Last)); 20 | 21 | const statusNum1 = num1.slice(0, num1.length - 1); 22 | const statusNum2 = num2.slice(0, num2.length - 1); 23 | 24 | if (statusNum1 === '' && statusNum2 === '') { 25 | const res = ans ? ans + sum.join('') : sum.join(''); 26 | ans = 0; 27 | sum = []; 28 | return res; 29 | } 30 | return addStrings(!statusNum1 ? '0' : statusNum1, !statusNum2 ? '0' : statusNum2); 31 | 32 | }; 33 | -------------------------------------------------------------------------------- /src/1.stack/12.包含min函数的栈.js: -------------------------------------------------------------------------------- 1 | /** 2 | * initialize your data structure here. 3 | */ 4 | const MinStack = function() { 5 | this.stack = []; 6 | }; 7 | 8 | /** 9 | * @param {number} x 10 | * @return {void} 11 | */ 12 | MinStack.prototype.push = function(x) { 13 | this.stack.push(x); 14 | }; 15 | 16 | /** 17 | * @return {void} 18 | */ 19 | MinStack.prototype.pop = function() { 20 | return this.stack.pop(); 21 | }; 22 | 23 | /** 24 | * @return {number} 25 | */ 26 | MinStack.prototype.top = function() { 27 | return this.stack[this.stack.length - 1]; 28 | }; 29 | 30 | /** 31 | * @return {number} 32 | */ 33 | MinStack.prototype.min = function() { 34 | return Math.min(...this.stack); 35 | }; 36 | 37 | /** 38 | * Your MinStack object will be instantiated and called as such: 39 | * var obj = new MinStack() 40 | * obj.push(x) 41 | * obj.pop() 42 | * var param_3 = obj.top() 43 | * var param_4 = obj.min() 44 | */ 45 | -------------------------------------------------------------------------------- /src/6.binary-tree/2.对称二叉树.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for a binary tree node. 3 | * function TreeNode(val, left, right) { 4 | * this.val = (val===undefined ? 0 : val) 5 | * this.left = (left===undefined ? null : left) 6 | * this.right = (right===undefined ? null : right) 7 | * } 8 | */ 9 | /** 10 | * @param {TreeNode} root 11 | * @return {boolean} 12 | */ 13 | const isSymmetric = function(root) { 14 | if (!root) return true; 15 | function isEqual(left, right) { 16 | // 两颗树的根节点相同,左侧树的left节点和右侧树的right节点相同 或者 左侧树的right节点和右侧树的left节点相同 17 | // 如果两个节点都为null 返回true 18 | // 如果两个节点有一个为null 返回 false 19 | if (!left && !right) return true; 20 | if (!left || !right) return false; 21 | return left.val === right.val && 22 | isEqual(left.left, right.right) && 23 | isEqual(left.right, right.left); 24 | } 25 | return isEqual(root.left, root.right); 26 | }; 27 | -------------------------------------------------------------------------------- /src/1.stack/13.栈的最小值.js: -------------------------------------------------------------------------------- 1 | /** 2 | * initialize your data structure here. 3 | */ 4 | const MinStack = function() { 5 | this.stack = []; 6 | }; 7 | 8 | /** 9 | * @param {number} x 10 | * @return {void} 11 | */ 12 | MinStack.prototype.push = function(x) { 13 | this.stack.push(x); 14 | }; 15 | 16 | /** 17 | * @return {void} 18 | */ 19 | MinStack.prototype.pop = function() { 20 | return this.stack.pop(); 21 | }; 22 | 23 | /** 24 | * @return {number} 25 | */ 26 | MinStack.prototype.top = function() { 27 | return this.stack[this.stack.length - 1]; 28 | }; 29 | 30 | /** 31 | * @return {number} 32 | */ 33 | MinStack.prototype.getMin = function() { 34 | return Math.min(...this.stack); 35 | }; 36 | 37 | /** 38 | * Your MinStack object will be instantiated and called as such: 39 | * var obj = new MinStack() 40 | * obj.push(x) 41 | * obj.pop() 42 | * var param_3 = obj.top() 43 | * var param_4 = obj.getMin() 44 | */ 45 | -------------------------------------------------------------------------------- /src/1.stack/14.最小栈.js: -------------------------------------------------------------------------------- 1 | /** 2 | * initialize your data structure here. 3 | */ 4 | const MinStack = function() { 5 | this.stack = []; 6 | }; 7 | 8 | /** 9 | * @param {number} val 10 | * @return {void} 11 | */ 12 | MinStack.prototype.push = function(val) { 13 | this.stack.push(val); 14 | }; 15 | 16 | /** 17 | * @return {void} 18 | */ 19 | MinStack.prototype.pop = function() { 20 | return this.stack.pop(); 21 | }; 22 | 23 | /** 24 | * @return {number} 25 | */ 26 | MinStack.prototype.top = function() { 27 | return this.stack[this.stack.length - 1]; 28 | }; 29 | 30 | /** 31 | * @return {number} 32 | */ 33 | MinStack.prototype.getMin = function() { 34 | return Math.min(...this.stack); 35 | }; 36 | 37 | /** 38 | * Your MinStack object will be instantiated and called as such: 39 | * var obj = new MinStack() 40 | * obj.push(val) 41 | * obj.pop() 42 | * var param_3 = obj.top() 43 | * var param_4 = obj.getMin() 44 | */ 45 | -------------------------------------------------------------------------------- /src/6.binary-tree/8.二叉树层次遍历.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for a binary tree node. 3 | * function TreeNode(val, left, right) { 4 | * this.val = (val===undefined ? 0 : val) 5 | * this.left = (left===undefined ? null : left) 6 | * this.right = (right===undefined ? null : right) 7 | * } 8 | */ 9 | /** 10 | * @param {TreeNode} root 11 | * @return {number[][]} 12 | */ 13 | const levelOrderBottom = function(root) { 14 | if (root == null) { 15 | return []; 16 | } 17 | const queue = [ root ]; // 借助队列来实现遍历 18 | const res = []; 19 | while (queue.length) { 20 | const subRes = []; 21 | const len = queue.length; 22 | for (let i = 0; i < len; i++) { 23 | const cur = queue.shift(); 24 | subRes.push(cur.val); 25 | if (cur.left) { 26 | queue.push(cur.left); 27 | } 28 | if (cur.right) { 29 | queue.push(cur.right); 30 | } 31 | } 32 | res.push(subRes); 33 | } 34 | return res.reverse(); 35 | }; 36 | -------------------------------------------------------------------------------- /src/5.linked-list/5.链表中倒数第k个节点.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for singly-linked list. 3 | * function ListNode(val) { 4 | * this.val = val; 5 | * this.next = null; 6 | * } 7 | */ 8 | /** 9 | * @param {ListNode} head 10 | * @param {number} k 11 | * @return {ListNode} 12 | */ 13 | const getKthFromEnd = function(head, k) { 14 | // const list = []; 15 | // while(head) { 16 | // list.push(head.val); 17 | // head = head.next; 18 | // } 19 | 20 | // let temp = list.slice(-k); 21 | // let newList = new ListNode(); 22 | // let prev = newList; 23 | // temp.forEach(v => { 24 | // const cur = new ListNode(v); 25 | // prev.next = cur; 26 | // prev = prev.next; 27 | // }) 28 | // return newList.next; 29 | // 快慢指针法 30 | let fast = head; 31 | let slow = head; 32 | let n = 0; 33 | while (fast) { 34 | if (n >= k) { 35 | slow = slow.next; 36 | } 37 | fast = fast.next; 38 | n++; 39 | } 40 | return slow; 41 | }; 42 | -------------------------------------------------------------------------------- /src/nativeJS/bind.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | global.a = 1; 3 | const obj = { a: 2 }; 4 | const fn = function(b, c, d, e) { console.log(this.a, b, c, d, e); return 1 } 5 | fn(1, 2) 6 | fn.bind(obj, 1, 2)(3) 7 | 8 | Function.prototype._bind = function(base, ...args1) { 9 | return (...args2) => { 10 | base = base || global; 11 | base.fn = this; 12 | const ret = base.fn(...args1, ...args2); 13 | delete base.fn; 14 | return ret 15 | } 16 | } 17 | fn._bind(obj, 1, 2)(3, 4) 18 | 19 | Function.prototype._bind1 = function(base, ...args) { 20 | return () => { 21 | base = base || window; 22 | base.fn = this; 23 | const ret = base.fn(...args, ...arguments); 24 | Reflect.deleteProperty(base, 'fn') 25 | return ret 26 | } 27 | } 28 | 29 | Function.prototype.bind1 = function(ctx, ...args) { 30 | return () => { 31 | ctx = ctx || window; 32 | ctx.fn = this; 33 | const ret = ctx.fn(...args, arguments) 34 | delete ctx.fn 35 | return ret 36 | } 37 | } -------------------------------------------------------------------------------- /src/6.binary-tree/21.二叉树的层平均值.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for a binary tree node. 3 | * function TreeNode(val, left, right) { 4 | * this.val = (val===undefined ? 0 : val) 5 | * this.left = (left===undefined ? null : left) 6 | * this.right = (right===undefined ? null : right) 7 | * } 8 | */ 9 | /** 10 | * @param {TreeNode} root 11 | * @return {number[]} 12 | */ 13 | const averageOfLevels = function(root) { 14 | if (!root) return []; 15 | const queue = [ root ]; 16 | const res = []; // 结果 17 | let level = 0; // 层级 18 | 19 | while (queue.length) { 20 | res[level] = []; 21 | 22 | let l = queue.length; 23 | while (l--) { 24 | const node = queue.shift(); 25 | res[level].push(node.val); 26 | if (node.left) { 27 | queue.push(node.left); 28 | } 29 | if (node.right) { 30 | queue.push(node.right); 31 | } 32 | } 33 | level++; 34 | } 35 | 36 | return res.map(num => num.reduce((prev, next) => prev + next, 0) / num.length); 37 | }; 38 | -------------------------------------------------------------------------------- /src/6.binary-tree/20.另一个树的子树.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for a binary tree node. 3 | * function TreeNode(val, left, right) { 4 | * this.val = (val===undefined ? 0 : val) 5 | * this.left = (left===undefined ? null : left) 6 | * this.right = (right===undefined ? null : right) 7 | * } 8 | */ 9 | /** 10 | * @param {TreeNode} root 11 | * @param {TreeNode} subRoot 12 | * @return {boolean} 13 | */ 14 | const isSubtree = function(r, s) { 15 | if (r == null) { 16 | return false; 17 | } 18 | if (isSameTree(r, s)) { 19 | return true; 20 | } 21 | return isSubtree(r.left, s) || isSubtree(r.right, s);// 只要有一个为true 就为true 22 | }; 23 | /* 24 | isSameTree 25 | 两树同为 null 则相同 26 | 一个 null 一个不是,则不同; 27 | 两个树都不为 null,则递归判断左右子树是否相同 28 | */ 29 | function isSameTree(r, s) { // 100题 30 | if (r == null && s == null) { 31 | return true; 32 | } 33 | if (r == null || s == null) { 34 | return false; 35 | } 36 | return r.val === s.val && isSameTree(r.left, s.left) && isSameTree(r.right, s.right); 37 | } 38 | -------------------------------------------------------------------------------- /src/3.string/11.字符串压缩.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {string} S 3 | * @return {string} 4 | */ 5 | const compressString = function(s) { 6 | let stack = []; 7 | let res = ''; 8 | for (let i = 0; i < s.length; i++) { 9 | if (!stack.length) { 10 | stack.push(s[i]); 11 | continue; 12 | } 13 | if (stack[stack.length - 1] === s[i]) { 14 | stack.push(s[i]); 15 | } else { 16 | res += stack[0] + stack.length; 17 | stack = []; 18 | stack.push(s[i]); 19 | } 20 | } 21 | res += stack[0] + stack.length; 22 | return s.length > res.length ? res : s; 23 | }; 24 | 25 | /** 26 | * @param {string} S 27 | * @return {string} 28 | */ 29 | const compressString1 = function(s) { 30 | let res = ''; 31 | let count = 1; 32 | let index = 0; 33 | while (index < s.length) { 34 | if (s[index] !== s[index + 1]) { 35 | res += s[index] + count; 36 | count = 1; 37 | } else { 38 | count++; 39 | } 40 | index++; 41 | } 42 | return s.length > res.length ? res : s; 43 | }; 44 | -------------------------------------------------------------------------------- /src/1.stack/5.化栈为队.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Initialize your data structure here. 3 | */ 4 | const MyQueue = function() { 5 | this.stack = []; 6 | }; 7 | 8 | /** 9 | * Push element x to the back of queue. 10 | * @param {number} x 11 | * @return {void} 12 | */ 13 | MyQueue.prototype.push = function(x) { 14 | this.stack.push(x); 15 | }; 16 | 17 | /** 18 | * Removes the element from in front of queue and returns that element. 19 | * @return {number} 20 | */ 21 | MyQueue.prototype.pop = function() { 22 | return this.stack.shift(); 23 | }; 24 | 25 | /** 26 | * Get the front element. 27 | * @return {number} 28 | */ 29 | MyQueue.prototype.peek = function() { 30 | return this.stack[0]; 31 | }; 32 | 33 | /** 34 | * Returns whether the queue is empty. 35 | * @return {boolean} 36 | */ 37 | MyQueue.prototype.empty = function() { 38 | return !this.stack.length; 39 | }; 40 | 41 | /** 42 | * Your MyQueue object will be instantiated and called as such: 43 | * var obj = new MyQueue() 44 | * obj.push(x) 45 | * var param_2 = obj.pop() 46 | * var param_3 = obj.peek() 47 | * var param_4 = obj.empty() 48 | */ 49 | -------------------------------------------------------------------------------- /src/6.binary-tree/4.二叉树最小深度.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for a binary tree node. 3 | * function TreeNode(val, left, right) { 4 | * this.val = (val===undefined ? 0 : val) 5 | * this.left = (left===undefined ? null : left) 6 | * this.right = (right===undefined ? null : right) 7 | * } 8 | */ 9 | /** 10 | * @param {TreeNode} root 11 | * @return {number} 12 | */ 13 | const minDepth = function(root) { 14 | // 注意题意:叶子节点是指没有子节点的节点。 15 | // 叶子节点的定义是左孩子和右孩子都为 null 时叫做叶子节点 16 | // 当 root 节点左右孩子都为空时,返回 1 17 | // 当 root 节点左右孩子有一个为空时,返回不为空的孩子节点的深度 18 | // 当 root 节点左右孩子都不为空时,返回左右孩子较小深度的节点值 19 | if (root == null) return 0; 20 | // 1.左孩子和右孩子都为空的情况,说明到达了叶子节点,直接返回1即可 21 | if (root.left == null && root.right == null) return 1; 22 | // 2.如果左孩子和右孩子其中一个为空,那么需要返回比较大的那个孩子的深度 23 | const minL = minDepth(root.left); 24 | const minR = minDepth(root.right); 25 | // 这里其中一个节点为空,说明m1和m2有一个必然为0,所以可以返回minL + minR + 1; 26 | if (root.left == null || root.right == null) return minL + minR + 1; 27 | 28 | // 3.最后一种情况,也就是左右孩子都不为空,返回最小深度+1即可 29 | return Math.min(minL, minR) + 1; 30 | }; 31 | -------------------------------------------------------------------------------- /src/1.stack/10.用队列实现栈.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Initialize your data structure here. 3 | */ 4 | const MyStack = function() { 5 | this.stack = []; 6 | }; 7 | 8 | /** 9 | * Push element x onto stack. 10 | * @param {number} x 11 | * @return {void} 12 | */ 13 | MyStack.prototype.push = function(x) { 14 | this.stack.push(x); 15 | }; 16 | 17 | /** 18 | * Removes the element on top of the stack and returns that element. 19 | * @return {number} 20 | */ 21 | MyStack.prototype.pop = function() { 22 | return this.stack.pop(); 23 | }; 24 | 25 | /** 26 | * Get the top element. 27 | * @return {number} 28 | */ 29 | MyStack.prototype.top = function() { 30 | return this.stack[this.stack.length - 1]; 31 | }; 32 | 33 | /** 34 | * Returns whether the stack is empty. 35 | * @return {boolean} 36 | */ 37 | MyStack.prototype.empty = function() { 38 | return this.stack.length === 0; 39 | }; 40 | 41 | /** 42 | * Your MyStack object will be instantiated and called as such: 43 | * var obj = new MyStack() 44 | * obj.push(x) 45 | * var param_2 = obj.pop() 46 | * var param_3 = obj.top() 47 | * var param_4 = obj.empty() 48 | */ 49 | -------------------------------------------------------------------------------- /src/1.stack/11.用栈操作构建数组.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[]} target 3 | * @param {number} n 4 | * @return {string[]} 5 | */ 6 | const buildArray = function(target, n) { 7 | const stack = []; 8 | if (target.length === n) { 9 | stack.length = n; 10 | stack.fill('Push'); 11 | return stack; 12 | } 13 | let index = 1; 14 | for (let i = 0; i < target.length; i++) { 15 | if (target[i] === index) { 16 | stack.push('Push'); 17 | } else { 18 | for (let j = 0; j < target[i] - index; j++) { 19 | stack.push('Push'); 20 | stack.push('Pop'); 21 | i--; 22 | } 23 | } 24 | index++; 25 | } 26 | return stack; 27 | }; 28 | // var buildArray = function (target, n) { 29 | // let stack = [], _stack = []; 30 | // for (let i = 0; i < n; i++) { 31 | // _stack.push(i + 1); 32 | // stack.push("Push"); 33 | // if (_stack[_stack.length - 1] !== target[_stack.length - 1]) { 34 | // stack.push("Pop"); 35 | // _stack.pop(); 36 | // } 37 | // if (target.length === _stack.length) return stack; 38 | // } 39 | // return stack; 40 | // }; 41 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "leetcode-js-roadmap", 3 | "version": "1.0.0", 4 | "description": "不积跬步无以至千里,许多人在学习算法的路上放弃,第一是因为起点太高,刚上来就做一些中等难度甚至困难的题,遇到挫折就很难坚持下去,就算刚开始从简单做起,也会在基础尚未牢固的情况下在中等难度下退缩;第二是因为没有路线图,在没有刷题规划的时候,就只能随缘打开任意一题开始了,同样很难坚持下来。 所以我特地把LeetCode上简单难度的题目根据数据结构进行分类,制定了一条无痛刷题路线图,相信这些简单题目能够让你得心应手,逐步培养算法题的自信心", 5 | "main": ".eslintrc.js", 6 | "scripts": { 7 | "lint": "eslint src --ext .js", 8 | "lint-fix": "eslint src --ext .js --fix --cache" 9 | }, 10 | "repository": { 11 | "type": "git", 12 | "url": "git+https://github.com/mengbo-ji/leetcode-js-roadmap.git" 13 | }, 14 | "keywords": [], 15 | "author": "", 16 | "license": "ISC", 17 | "bugs": { 18 | "url": "https://github.com/mengbo-ji/leetcode-js-roadmap/issues" 19 | }, 20 | "homepage": "https://github.com/mengbo-ji/leetcode-js-roadmap#readme", 21 | "devDependencies": { 22 | "eslint": "^7.28.0", 23 | "eslint-config-rc": "^1.0.2", 24 | "git-pre-hooks": "^1.2.1" 25 | }, 26 | "git-pre-hooks": { 27 | "pre-commit": "npm run lint" 28 | }, 29 | "dependencies": { 30 | "lodash": "^4.17.21" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/4.array/7.最大子序的和.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[]} nums 3 | * @return {number} 4 | */ 5 | const maxSubArray = function(nums) { 6 | if (nums.length === 1) { 7 | return nums[0]; 8 | } 9 | let max = 0; 10 | for (let i = 0; i < nums.length; i++) { 11 | const res = []; 12 | let prev = nums[i]; 13 | for (let j = i + 1; j < nums.length; j++) { 14 | res.push(prev + nums[j]); 15 | prev = prev + nums[j]; 16 | } 17 | 18 | const maxTemp = Math.max(...res); 19 | if (maxTemp > max) { 20 | max = maxTemp; 21 | } 22 | } 23 | 24 | return nums.sort((a, b) => b - a).some(v => v > max) || max === 0 ? nums[0] : max; 25 | }; 26 | 27 | /** 28 | * @param {number[]} nums 29 | * @return {number} 30 | */ 31 | const maxSubArray1 = function(nums) { 32 | // 1.假如全是负数,那就是找最大值即可,因为负数肯定越加越大。 2.如果有正数,则肯定从正数开始计算和,不然前面有负值,和肯定变小了,所以从正数开始。 3.当和小于零时,这个区间就告一段落了,然后从下一个正数重新开始计算(也就是又回到 2 了)。而 dp 也就体现在这个地方 33 | let sum = 0, 34 | ans = nums[0]; 35 | for (const v of nums) { 36 | if (sum > 0) { 37 | sum += v; 38 | } else { 39 | sum = v; 40 | } 41 | ans = Math.max(ans, sum); 42 | } 43 | 44 | return ans; 45 | }; 46 | -------------------------------------------------------------------------------- /src/6.binary-tree/15.二叉搜索树的最近公共祖先.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for a binary tree node. 3 | * function TreeNode(val) { 4 | * this.val = val; 5 | * this.left = this.right = null; 6 | * } 7 | */ 8 | 9 | /** 10 | * @param {TreeNode} root 11 | * @param {TreeNode} p 12 | * @param {TreeNode} q 13 | * @return {TreeNode} 14 | */ 15 | const lowestCommonAncestor = function(root, p, q) { 16 | // 根据二叉搜索树性质:如果 p.val 和 q.val 都比 root.val 小,则 p、q 肯定在 root 的左子树。 17 | // 那问题规模就变小了,递归左子树就行! 18 | // 如果 p.val 和 q.val 都比 root.val 大,递归右子树就行! 19 | // 其他情况,root 即为所求!那么简单吗?为什么? 20 | // 只要不是 p.val 和 q.val 都大于(小于) root.val,即只要 p, q 不同处在 root 的一个子树 21 | // 就只有这三种情况: 22 | // p 和 q 分居 root 的左、右子树。 23 | // root 就是 p,q 在 p 的子树中。 24 | // root 就是 q,p 在 q 的子树中 25 | // 而这三种情况,p 和 q 的最近公共祖先都是 root!是不是很简单! 26 | // if (p.val > root.val && q.val > root.val) { 27 | // return lowestCommonAncestor(root.right, p, q) 28 | // } 29 | // if (p.val < root.val && q.val < root.val) { 30 | // return lowestCommonAncestor(root.left, p, q) 31 | // } 32 | // return root; 33 | 34 | // 迭代版本 35 | while (root) { 36 | if (p.val > root.val && q.val > root.val) { 37 | root = root.right; 38 | } else if (p.val < root.val && q.val < root.val) { 39 | root = root.left; 40 | } else { 41 | break; 42 | } 43 | } 44 | return root; 45 | }; 46 | -------------------------------------------------------------------------------- /src/1.stack/16.整理字符串.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {string} s 3 | * @return {string} 4 | */ 5 | // const makeGood = function(s) { 6 | // const stack = []; 7 | // stack.push(s[0]); 8 | // for (let i = 1; i < s.length; i++) { 9 | // const prev = stack[stack.length - 1]; 10 | // const next = s[i]; 11 | // if (prev) { 12 | // // 大写 13 | // if (prev === prev.toUpperCase()) { 14 | // if (next === prev.toLowerCase()) { 15 | // stack.pop(); 16 | // } else { 17 | // stack.push(next); 18 | // } 19 | // } 20 | // // 小写 21 | // if (prev === prev.toLowerCase()) { 22 | // if (next === prev.toUpperCase()) { 23 | // stack.pop(); 24 | // } else { 25 | // stack.push(next); 26 | // } 27 | // } 28 | // } else { 29 | // stack.push(s[i]); 30 | // } 31 | // } 32 | 33 | // return stack.join(''); 34 | // }; 35 | 36 | const makeGood = function(s) { 37 | const res = []; 38 | for (const v of s) { 39 | if (res.length && 40 | res[res.length - 1] !== v && 41 | res[res.length - 1].toUpperCase() === v.toUpperCase()) { 42 | res.pop(); 43 | } else { 44 | res.push(v); 45 | } 46 | } 47 | return res.join(''); 48 | }; 49 | -------------------------------------------------------------------------------- /src/lodash/strongThrottle.js: -------------------------------------------------------------------------------- 1 | const { now } = require('lodash'); 2 | 3 | function throttle(fn, delay) { 4 | let timer = null; 5 | let lastTime = 0; 6 | return function(...args) { 7 | const ctx = this; 8 | const nowTime = +new Date(); 9 | if (nowTime - lastTime < delay) { 10 | if (timer) clearTimeout(timer); 11 | timer = setTimeout(function() { 12 | lastTime = nowTime; 13 | fn.apply(ctx, args); 14 | }, delay); 15 | } else { 16 | // 这个时候表示时间到了,必须给响应 17 | lastTime = nowTime; 18 | fn.apply(ctx, args); 19 | } 20 | }; 21 | } 22 | 23 | function strongThrottle(fn, delay) { 24 | let timer = null; 25 | let prevTime = 0; 26 | return (...args) => { 27 | const nowTime = +new Date(); 28 | if (nowTime - prevTime < delay) { 29 | if (timer) clearTimeout(timer); 30 | timer = setTimeout(() => { 31 | prevTime = nowTime; 32 | fn(...args); 33 | }, delay); 34 | } else { 35 | fn(...args); 36 | prevTime = nowTime; 37 | } 38 | }; 39 | } 40 | 41 | function strongThrottle2(fn, delay) { 42 | let timer = null; 43 | let lastTime = 0; 44 | return (...args) => { 45 | const nowTime = +new Date(); 46 | if (nowTime - lastTime < delay) { 47 | clearTimeout(timer); 48 | timer = setTimeout(() => { 49 | fn(...args); 50 | lastTime = nowTime; 51 | }, delay); 52 | } else { 53 | fn(...args); 54 | lastTime = nowTime; 55 | } 56 | }; 57 | } 58 | -------------------------------------------------------------------------------- /src/lodash/add(1)(2)(3).js: -------------------------------------------------------------------------------- 1 | 2 | // 计算函数,收集到所有函数的参数之后, 计算结果并返回 3 | const compute = (...args) => { 4 | return args.reduce((prev, next) => prev + next); 5 | }; 6 | 7 | const currying = fn => { 8 | // 利用闭包,将计算函数fn和参数数组args先保存下来,fn = compute, args 是所有函数传入进来的参数数组 9 | let args = []; 10 | return function temp(...newArgs) { 11 | // 如果参数存在 说明还要继续去添加到args中 12 | if (newArgs.length) { 13 | args = [ 14 | ...args, 15 | ...newArgs, 16 | ]; 17 | // 将当前函数继续return 出去 继续去收集参数 18 | return temp; 19 | } 20 | // 如果参数不存在 说明 到了调用的时候() 21 | // 那么这个时候只需要将收集到参数数组 args 传入到计算函数并且将计算的值返回 22 | const res = fn.apply(this, args); 23 | args = []; // 将args重置为空 24 | return res; 25 | }; 26 | }; 27 | 28 | const fnCurry = currying(compute); 29 | 30 | // 测试下 31 | console.log(fnCurry(1)(2)(3)(4)(5)()); 32 | console.log(fnCurry(1, 2, 3)(4)(5)()); 33 | 34 | 35 | // 计算函数 36 | const complute = (...args) => { 37 | return args.reduce((prev, next) => prev + next, 0); 38 | }; 39 | 40 | 41 | const currying1 = fn => { 42 | let args = []; 43 | return function temp(...newArgs) { 44 | if (newArgs.length) { 45 | args = [ 46 | ...args, 47 | ...newArgs, 48 | ]; 49 | return temp; 50 | } 51 | const res = fn.apply(this, args); 52 | args = []; 53 | return res; 54 | }; 55 | }; 56 | 57 | const fnCurry1 = currying1(complute); 58 | 59 | // 测试下 60 | console.log(fnCurry1(1)(2)(3)(4)(5)()); 61 | console.log(fnCurry1(1, 2, 3)(4)(5)()); 62 | -------------------------------------------------------------------------------- /src/1.stack/9.下一个更大元素.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[]} nums1 3 | * @param {number[]} nums2 4 | * @return {number[]} 5 | */ 6 | // const nextGreaterElement = function(nums1, nums2) { 7 | // let res = []; 8 | // for (let i = 0; i < nums1.length; i++) { 9 | // let index = 0; 10 | // let value = nums1[i]; 11 | // for (let j = 0; j < nums2.length; j++) { 12 | // if (nums1[i] === nums2[j]) { 13 | // index = j + 1; 14 | // continue; 15 | // } 16 | // } 17 | // const arr = nums2.slice(index); 18 | // let l = 0; 19 | // let flag = false; 20 | // while(l !== arr.length){ 21 | // if (arr[l++] > value) { 22 | // res.push(arr[l - 1]); 23 | // flag = true; 24 | // break; 25 | // } 26 | // } 27 | // if (flag) { 28 | // flag = false; 29 | // } else { 30 | // res.push(-1); 31 | // } 32 | // } 33 | // return res; 34 | // }; 35 | const nextGreaterElement = function(nums1, nums2) { 36 | const map = new Map(), 37 | stack = [], 38 | ans = []; 39 | nums2.forEach(item => { 40 | while (stack.length && item > stack[stack.length - 1]) { 41 | map.set(stack.pop(), item); 42 | } 43 | stack.push(item); 44 | }); 45 | console.log('map', map); 46 | console.log('stack', ans); 47 | console.log('ans', ans); 48 | stack.forEach(item => map.set(item, -1)); 49 | nums1.forEach(item => ans.push(map.get(item))); 50 | return ans; 51 | }; 52 | 53 | -------------------------------------------------------------------------------- /src/6.binary-tree/14.二叉树的所有路径.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for a binary tree node. 3 | * function TreeNode(val, left, right) { 4 | * this.val = (val===undefined ? 0 : val) 5 | * this.left = (left===undefined ? null : left) 6 | * this.right = (right===undefined ? null : right) 7 | * } 8 | */ 9 | /** 10 | * @param {TreeNode} root 11 | * @return {string[]} 12 | */ 13 | const binaryTreePaths = function(root) { 14 | // 广度优先遍历 15 | // const paths = []; 16 | // if (root === null) return paths; 17 | 18 | // const nodeQueue = [root]; 19 | // const pathQueue = [root.val.toString()]; 20 | 21 | // while(nodeQueue.length) { 22 | // const node = nodeQueue.shift(); 23 | // const path = pathQueue.shift(); 24 | // if (node.left === null && node.right === null) { 25 | // paths.push(path); 26 | // } else { 27 | // if (node.left !== null) { 28 | // nodeQueue.push(node.left); 29 | // pathQueue.push(path + '->' + node.left.val.toString()) 30 | // } 31 | // if (node.right !== null) { 32 | // nodeQueue.push(node.right); 33 | // pathQueue.push(path + '->' + node.right.val.toString()) 34 | // } 35 | // } 36 | // } 37 | // return paths; 38 | 39 | 40 | // 深度优先 41 | const paths = []; 42 | function getH(root, path) { 43 | if (root) { 44 | path += root.val.toString(); 45 | if (root.left === null && root.right === null) { 46 | paths.push(path); 47 | } else { 48 | path += '->'; 49 | getH(root.left, path); 50 | getH(root.right, path); 51 | } 52 | } 53 | } 54 | getH(root, ''); 55 | return paths; 56 | }; 57 | -------------------------------------------------------------------------------- /src/lodash/chunk.js: -------------------------------------------------------------------------------- 1 | const _ = require('lodash'); 2 | const arr = [ 1, 2, 3, 4 ]; 3 | console.log('_.chunk(arr, 2);', _.chunk(arr, 2)); 4 | 5 | // const _chunk = (input, size) => { 6 | // return input.reduce((arr, item, idx) => { 7 | // const currentArr = idx % size === 0 8 | // ? [ ...arr, [ item ]] 9 | // : [ ...arr.slice(0, -1), [ ...arr.slice(-1)[0], item ]]; 10 | // return currentArr; 11 | // }, []); 12 | // }; 13 | 14 | 15 | const _chunk = (array, size = 1) => { 16 | size = Math.max(size, 0); 17 | const length = array == null ? 0 : array.length; 18 | if (!length || size < 1) { 19 | return []; 20 | } 21 | let index = 0; 22 | let resultIndex = 0; 23 | const result = new Array(Math.ceil(length / size)); 24 | while (index < length) { 25 | result[resultIndex++] = array.slice(index, index += size); 26 | } 27 | return result; 28 | }; 29 | 30 | console.log('_chunk', _chunk(arr)); 31 | 32 | const _chunk1 = (array, size) => { 33 | size = Math.max(size, 0); 34 | const length = array == null ? 0 : array.length; 35 | if (!length || size < 1) { 36 | return []; 37 | } 38 | 39 | let index = 0; 40 | let resultIndex = 0; 41 | const result = []; 42 | while (index < length) { 43 | result[resultIndex++] = array.slice(index, index += size); 44 | } 45 | return result; 46 | }; 47 | 48 | const _chunk2 = (array, size) => { 49 | size = Math.max(size, 0); 50 | const length = array == null ? 0 : array.length; 51 | if (!length || size < 1) { 52 | return []; 53 | } 54 | 55 | let index = 0; 56 | let resultIndex = 0; 57 | const result = []; 58 | while (index < length) { 59 | result[resultIndex++] = array.slice(index, index += size); 60 | } 61 | return result; 62 | }; 63 | 64 | -------------------------------------------------------------------------------- /src/lodash/curry.js: -------------------------------------------------------------------------------- 1 | 2 | // 模拟lodash中的curry方法 3 | // const curry = require('lodash').curry; 4 | 5 | function getSum(a, b, c) { 6 | return a + b + c; 7 | } 8 | 9 | function curry(fn) { 10 | return function temp(...args) { 11 | if (args.length < fn.length) { 12 | return function() { 13 | return temp(...args, ...arguments); 14 | }; 15 | } 16 | return fn(...args); 17 | }; 18 | } 19 | 20 | const curried = curry(getSum); 21 | 22 | // console.log(curried(1, 2, 3)); 23 | // console.log(curried(1)(2)(3)); 24 | // console.log(curried(1)(2, 3)); 25 | 26 | 27 | function curry1(fn) { 28 | return function temp(...args) { 29 | if (args.length < fn.length) { 30 | return function() { 31 | return temp(...args, ...arguments); 32 | }; 33 | } 34 | return fn(...args); 35 | }; 36 | } 37 | 38 | const curried1 = curry1(getSum); 39 | 40 | function curry2(fn) { 41 | return function temp(...args) { 42 | if (args.length < fn.length) { 43 | return function() { 44 | return temp(...args, ...arguments); 45 | }; 46 | } 47 | return fn(...args); 48 | }; 49 | } 50 | 51 | console.log(curried1(1, 2, 3)); 52 | console.log(curried1(1)(2)(3)); 53 | console.log(curried1(1)(2, 3)); 54 | 55 | function curry3(fn) { 56 | return function temp(...args) { 57 | if (args.length < fn.length) { 58 | return function() { 59 | return temp(...args, arguments); 60 | }; 61 | } 62 | return fn(...args); 63 | }; 64 | } 65 | 66 | function curry4(fn) { 67 | return function temp(...args) { 68 | if (args.length < fn.length) { 69 | return function() { 70 | return temp(...args, arguments); 71 | }; 72 | } 73 | return fn(...args); 74 | }; 75 | } 76 | -------------------------------------------------------------------------------- /src/4.array/18.顺时针打印矩阵.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[][]} matrix 3 | * @return {number[]} 4 | */ 5 | 6 | /** 7 | 如果一条边从头遍历到底,则下一条边遍历的起点随之变化。如果不遍历到底,可以减小横向和竖向遍历之间的影响。 8 | 我选择一次迭代遍历一个“圈”,然后 4 条边的两端同时收缩,一层层向内处理,按顺时针依次遍历:上、右、下、左层。 9 | 不再形成“环”了就结束遍历,剩下一行或一列,然后单独判断即可。 10 | 上边界 top : 0 11 | 下边界 bottom : matrix.length - 1 12 | 左边界 left : 0 13 | 右边界 right : matrix[0].length - 1 14 | 矩阵不一定是方阵 15 | top < bottom && left < right 是循环的条件。 16 | 结束循环时,分 3 种情况: 17 | top == bottom && left < right —— 剩一行。 18 | top < bottom && left == right —— 剩一列。 19 | top == bottom && left == right —— 剩一项(也是一行/列)。 20 | 处理剩下的单行或单列 21 | 因为是按顺时针推入结果数组的,所以: 22 | 剩下的一行,从左至右 依次推入结果数组。 23 | 剩下的一列,从上至下 依次推入结果数组。 24 | */ 25 | const spiralOrder = function(matrix) { 26 | if (!matrix.length) { 27 | return []; 28 | } 29 | const res = []; 30 | let top = 0; 31 | let right = matrix[0].length - 1; 32 | let bottom = matrix.length - 1; 33 | let left = 0; 34 | 35 | while (top < bottom && left < right) { 36 | // 左—右 37 | for (let i = left; i < right; i++) { 38 | res.push(matrix[top][i]); 39 | } 40 | // 上-下 41 | for (let i = top; i < bottom; i++) { 42 | res.push(matrix[i][right]); 43 | } 44 | // 右-左 45 | for (let i = right; i > left; i--) { 46 | res.push(matrix[bottom][i]); 47 | } 48 | // 下-上 49 | for (let i = bottom; i > top; i--) { 50 | res.push(matrix[i][left]); 51 | } 52 | top++; 53 | right--; 54 | bottom--; 55 | left++; 56 | } 57 | 58 | // 如果只剩一列 59 | if (left === right && top !== bottom) { 60 | for (let i = top; i <= bottom; i++) { 61 | res.push(matrix[i][left]); 62 | } 63 | // 如果只剩一行 64 | } else if (top === bottom && left !== right) { 65 | for (let i = left; i <= right; i++) { 66 | res.push(matrix[top][i]); 67 | } 68 | // 只剩单个 69 | } else if (top === bottom && left === right) { 70 | res.push(matrix[top][left]); 71 | } 72 | 73 | return res; 74 | }; 75 | -------------------------------------------------------------------------------- /src/lodash/observer.js: -------------------------------------------------------------------------------- 1 | // 14发布订阅 2 | 3 | class Observer { 4 | caches = {}; 5 | 6 | on(eventName, cb) { 7 | this.caches[eventName] = this.caches[eventName] || []; 8 | this.caches[eventName].push(cb); 9 | } 10 | 11 | emit(eventName, payload) { 12 | if (this.caches[eventName]) { 13 | this.caches[eventName].forEach(cb => cb(payload)); 14 | } 15 | } 16 | 17 | off(eventName, cb) { 18 | if (this.caches[eventName]) { 19 | const newCaches = cb ? this.caches[eventName].filter(fn => fn !== cb) : []; 20 | this.caches[eventName] = newCaches; 21 | } 22 | } 23 | } 24 | 25 | class MyEvent { 26 | _events = {}; 27 | 28 | on(eventName, cb) { 29 | this._events[eventName] = this._events[eventName] || []; 30 | this._events[eventName].push(cb); 31 | } 32 | 33 | once(eventName, cb) { 34 | const tempFn = (...args) => { 35 | cb(...args); 36 | this.off(eventName, tempFn); 37 | }; 38 | tempFn.link = cb; 39 | this.on(eventName, tempFn); 40 | } 41 | 42 | emit(eventName, ...args) { 43 | if (this._events[eventName]) { 44 | this._events[eventName].forEach(fn => fn(...args)); 45 | } 46 | } 47 | 48 | off(eventName, cb) { 49 | if (this._events[eventName]) { 50 | const newEvents = cb ? this._events[eventName].filter(fn => fn !== cb && fn.link !== cb) : []; 51 | this._events[eventName] = newEvents; 52 | } 53 | } 54 | } 55 | 56 | const event = new MyEvent(); 57 | const fn = payload => { 58 | console.log('事件1执行了', payload); 59 | }; 60 | event.once('事件1', fn); 61 | event.emit('事件1', 1); 62 | event.emit('事件1', 2); 63 | 64 | class Observer2 { 65 | _events = {} 66 | 67 | on(eventName, cb) { 68 | this._events[eventName] = this._events[eventName] || []; 69 | this._events[eventName].push(cb); 70 | } 71 | emit(eventName, payload) { 72 | if (this._events[eventName]) { 73 | this._events[eventName].forEach(cb => cb(payload)); 74 | } 75 | } 76 | off(eventName, cb) { 77 | if (this._events[eventName]) { 78 | const newEvents = cb ? this._events[eventName].filter(v => cb !== v) : []; 79 | this._events[eventName] = newEvents; 80 | } 81 | } 82 | } 83 | 84 | -------------------------------------------------------------------------------- /src/Promise/test.js: -------------------------------------------------------------------------------- 1 | 2 | const MyPromise = require('./myPromise'); 3 | const { pathEq } = require('lodash/fp'); 4 | const { values } = require('lodash'); 5 | 6 | function other() { 7 | return new MyPromise((resolve, reject) => { 8 | resolve('ohter'); 9 | }); 10 | } 11 | 12 | // const promise = new MyPromise((resolve, reject) => { 13 | // // throw new Error('执行器报错捕获'); 14 | // setTimeout(() => { 15 | // resolve('成功'); 16 | // }, 2000); 17 | // // resolve('成功'); 18 | // // reject('失败'); 19 | // }); 20 | 21 | // const p1 = promise.then(value => { 22 | // console.log('value1', value); 23 | // // return other(); 24 | // // return p1; 25 | // // throw new Error('then 报错捕获'); 26 | // return 'aaa'; 27 | // }, error => { 28 | // console.log('error1', error); 29 | // return '10000000'; 30 | // }); 31 | 32 | // p1.then(value => { 33 | // console.log('value2', value); 34 | // }, error => { 35 | // console.log('error2', error.message); 36 | // }); 37 | 38 | // const p2 = new MyPromise((resolve, reject) => { 39 | // // resolve('成功'); 40 | // reject('失败'); 41 | // }); 42 | 43 | // p2.then().then().then(value => console.log('value3', value)); 44 | // p2.then().then().then(value => console.log('value4', value), error => console.log('error4', error)); 45 | 46 | function p1() { 47 | return new MyPromise((resolve, reject) => { 48 | setTimeout(() => { 49 | resolve('p1'); 50 | }, 1000); 51 | }); 52 | } 53 | 54 | function p2() { 55 | return new MyPromise((resolve, reject) => { 56 | // resolve('p2 resolve'); 57 | reject('p2 reject'); 58 | }); 59 | } 60 | 61 | // MyPromise.all([ 'a', 'b', p1(), p2(), 'c', 'd' ]).then(result => { 62 | // console.log('result', result); 63 | // }); 64 | 65 | // MyPromise.resolve(100).then(value => console.log(value)); 66 | // MyPromise.resolve(p1()).then(value => console.log(value)); 67 | 68 | // p2() 69 | // .finally(() => { 70 | // console.log('finally'); 71 | // return p1(); 72 | // }) 73 | // .then(value => { console.log(value); }, 74 | // error => console.log(error)) 75 | // .then(value => console.log('value1', value), 76 | // error => console.log('error1', error)); 77 | 78 | p2() 79 | .then(value => console.log(value)) 80 | .catch(error => console.log(error)); 81 | -------------------------------------------------------------------------------- /src/lodash/iterable.js: -------------------------------------------------------------------------------- 1 | // 实现对象的 iterable接口 2 | 3 | // const obj = { 4 | // store: [ 'foo', 'bar', 'jmb' ], 5 | // [Symbol.iterator]() { 6 | // const self = this; 7 | // let index = 0; 8 | // return { 9 | // next() { 10 | // const result = { 11 | // value: self.store[index], 12 | // done: index >= self.store.length, 13 | // }; 14 | // index++; 15 | // return result; 16 | // }, 17 | // }; 18 | // }, 19 | // }; 20 | 21 | // for (const item of obj) { 22 | // console.log('item', item); 23 | // } 24 | 25 | 26 | const todos = { 27 | life: [ '吃饭', '睡觉', '❤️' ], 28 | learn: [ '学习', '敲代码', '提升' ], 29 | work: [ '工作', '开会' ], 30 | each(callback) { 31 | const all = [ ...this.life, ...this.learn, ...this.work ]; 32 | for (const item of all) { 33 | callback(item); 34 | } 35 | }, 36 | [Symbol.iterator]() { 37 | const all = [ ...this.life, ...this.learn, ...this.work ]; 38 | let index = 0; 39 | return { 40 | next() { 41 | const result = { 42 | value: all[index], 43 | done: index++ >= all.length, 44 | }; 45 | return result; 46 | }, 47 | }; 48 | }, 49 | }; 50 | 51 | // for (const item of todos.life) { 52 | // console.log(item); 53 | // } 54 | 55 | // for (const item of todos.learn) { 56 | // console.log(item); 57 | // } 58 | 59 | // for (const item of todos.work) { 60 | // console.log(item); 61 | // } 62 | 63 | // todos.each(item => { 64 | // console.log(item); 65 | // }); 66 | 67 | // for (const item of todos) { 68 | // console.log(item); 69 | // } 70 | 71 | 72 | // 2. 采用Generator接口实现iterable接口 73 | 74 | 75 | const todos1 = { 76 | life: [ '吃饭', '睡觉', '❤️' ], 77 | learn: [ '学习', '敲代码', '提升' ], 78 | work: [ '工作', '开会' ], 79 | each(callback) { 80 | const all = [ ...this.life, ...this.learn, ...this.work ]; 81 | for (const item of all) { 82 | callback(item); 83 | } 84 | }, 85 | *[Symbol.iterator]() { 86 | const all = [ ...this.life, ...this.learn, ...this.work ]; 87 | for (const item of all) { 88 | yield item; 89 | } 90 | }, 91 | }; 92 | 93 | 94 | for (const item of todos1) { 95 | console.log(item, 'item'); 96 | } 97 | 98 | const obj1 = { 99 | html: 4, 100 | css: 3, 101 | javascript: 100, 102 | }; 103 | 104 | for (const [ key, value ] of Object.entries(obj1)) { 105 | // console.log(key, value); 106 | console.log(`${key.padEnd(16, '-')}|${value.toString().padStart(3, '0')}`); 107 | } 108 | -------------------------------------------------------------------------------- /src/Promise/promise.js: -------------------------------------------------------------------------------- 1 | 2 | class MyPromise { 3 | constructor(exector) { 4 | try { 5 | exector(this.resolve, this.reject); 6 | } catch (error) { 7 | this.reject(error); 8 | } 9 | } 10 | status = 'pending' 11 | value = undefined; 12 | reason = undefined; 13 | resolve = value => { 14 | if (this.status === 'pending') { 15 | this.status = 'fulfilled'; 16 | this.value = value; 17 | } 18 | } 19 | reject = reason => { 20 | if (this.status === 'pending') { 21 | this.status = 'rejected'; 22 | this.reason = reason; 23 | } 24 | } 25 | then = (successCallback, failCallback) => { 26 | if (this.status === 'fulfilled') { 27 | successCallback(this.value); 28 | } else if (this.status === 'rejected') { 29 | failCallback(this.reason); 30 | } 31 | } 32 | } 33 | 34 | const x = new MyPromise((resolve, reject) => { 35 | resolve(1); 36 | }); 37 | 38 | x.then(value => { 39 | console.log(value); 40 | }); 41 | 42 | class MyPromise1 { 43 | constructor(exector) { 44 | try { 45 | exector(this.resolve, this.reject); 46 | } catch (error) { 47 | this.reject(error); 48 | } 49 | } 50 | status = 'pending'; 51 | value = undefined; 52 | reason = undefined; 53 | resolve(value) { 54 | if (this.status === 'pending') { 55 | this.status = 'fulfilled'; 56 | this.value = value; 57 | } 58 | } 59 | reject(reason) { 60 | if (this.status === 'pending') { 61 | this.status = 'rejected'; 62 | this.reason = reason; 63 | } 64 | } 65 | then(successCb, failCb) { 66 | if (this.status === 'fulfilled') { 67 | successCb(this.value); 68 | } else if (this.status === 'rejected') { 69 | failCb(this.reason); 70 | } 71 | } 72 | } 73 | 74 | class Promise1 { 75 | constructor(exector) { 76 | try { 77 | exector(this.resolve, this.reject); 78 | } catch (error) { 79 | this.reject(error); 80 | } 81 | } 82 | status = 'pending' // pending success rejected 83 | reason = null 84 | value = null 85 | 86 | resolve(value) { 87 | if (this.status === 'pending') { 88 | this.status = 'success'; 89 | this.value = value; 90 | } 91 | } 92 | 93 | reject(reason) { 94 | if (this.status === 'pending') { 95 | this.status = 'rejected'; 96 | this.reason = reason; 97 | } 98 | } 99 | 100 | then(successCb, rejectedCb) { 101 | if (this.status === 'success') { 102 | successCb(this.value); 103 | } else if (this.status === 'rejected') { 104 | rejectedCb(this.reason); 105 | } 106 | } 107 | 108 | } 109 | 110 | new MyPromise((resolve, reject) => { 111 | resolve(); 112 | reject(); 113 | }); 114 | -------------------------------------------------------------------------------- /src/lodash/get.js: -------------------------------------------------------------------------------- 1 | function get(source, path, defaultValue) { 2 | if (typeof source !== 'object' || typeof path !== 'string') { 3 | return; 4 | } 5 | // 正则匹配 [0] 这种情况, 6 | // $1 就是第一个小括号匹配到的内容,.$! = .0 7 | // arr[0].a => arr.0.a => [arr, 0, a] 8 | // [0].a.b => [ '', '0', 'a', 'b' ].filter(Boolean) 9 | const paths = path.replace(/\[(\d+)\]/g, '.$1').split('.').filter(Boolean); 10 | let res = source; 11 | for (const p of paths) { 12 | // 要注意null和undefined 取属性报错 13 | res = Object(res)[p]; 14 | if (res === undefined) { 15 | return defaultValue; 16 | } 17 | } 18 | return res; 19 | } 20 | 21 | const obj = { 22 | arr: [ 23 | { 24 | a: 1, 25 | }, 26 | ], 27 | p: { 28 | c: 'i', 29 | }, 30 | }; 31 | 32 | // console.log(get(obj, 'arr[0].a', 0)); // output: 1 33 | // console.log(get({ a: null }, 'a.b.c', 2)); // output: 2 34 | // console.log(get({ a: undefined }, 'a', 1)); // output: 1 35 | // console.log(get({ a: null }, 'a', 3)); // output: null 36 | // console.log(get({ a: [{ b: 1 }] }, 'a[0].b', 3)); // output: 1 37 | // console.log(get([{ a: { b: 111 } }], '[0].a.b', 3)); // output: 111 38 | 39 | // 不考虑 [] 的情况 40 | const _get = (object, keys, val) => { 41 | return keys.split(/\./).reduce((prev, next) => ((prev || {})[next]), object) || val; 42 | }; 43 | 44 | // console.log(get({ a: null }, 'a.b.c', 3)); // output: 3 45 | // console.log(get({ a: undefined }, 'a', 3)); // output: 3 46 | // console.log(get({ a: null }, 'a', 3)); // output: null 47 | // console.log(get({ a: { b: 1 } }, 'a.b', 3)); // output: 1 48 | 49 | function get1(source, path, defaultValue) { 50 | if (typeof source !== 'object' || typeof path !== 'string') { 51 | return; 52 | } 53 | const paths = path.replace(/\[(\d+)\]/g, '.$1').split('.').filter(Boolean); 54 | let res = source; 55 | for (const p of paths) { 56 | res = Object(res)[p]; 57 | if (res === undefined) { 58 | return defaultValue; 59 | } 60 | } 61 | return res; 62 | } 63 | 64 | 65 | function get2(source, path, defaultValue) { 66 | const paths = path.replace(/\[(\d+)\]/g, '.$1').split('.').filter(Boolean); 67 | let res = source; 68 | for (const p of paths) { 69 | res = Object(res)[p]; 70 | if (res === undefined) { 71 | return defaultValue; 72 | } 73 | } 74 | return res; 75 | } 76 | 77 | console.log(get1({ a: null }, 'a.b.c', 3)); // output: 3 78 | console.log(get1({ a: undefined }, 'a', 3)); // output: 3 79 | console.log(get1({ a: null }, 'a', 3)); // output: null 80 | console.log(get1({ a: { b: 1 } }, 'a.b', 3)); // output: 1 81 | 82 | function get3(source, path, defaultValue) { 83 | const paths = path.replace(/\[(\d+)\]/g, '.$1').split('.').filter(Boolean); 84 | let res = source; 85 | for (const p of paths) { 86 | res = Object(res)[p]; 87 | if (res === undefined) { 88 | return defaultValue; 89 | } 90 | } 91 | return res; 92 | } 93 | -------------------------------------------------------------------------------- /src/lodash/洋葱模型.js: -------------------------------------------------------------------------------- 1 | 2 | const middleware = []; 3 | 4 | middleware.push(async (ctx, next) => { 5 | console.log('第一个中间件前'); 6 | await next(); 7 | console.log('第一个中间件后'); 8 | }); 9 | 10 | middleware.push(async (ctx, next) => { 11 | console.log('第二个中间件前'); 12 | await next(); 13 | console.log('第二个中间件后'); 14 | }); 15 | 16 | middleware.push(async (ctx, next) => { 17 | console.log('第三个中间件前'); 18 | await next(); 19 | console.log('第三个中间件后'); 20 | }); 21 | 22 | middleware.push(async (ctx, next) => { 23 | console.log('第四个中间件前'); 24 | await next(); 25 | console.log('第四个中间件后'); 26 | }); 27 | 28 | const ctx = {}; 29 | 30 | compose2(middleware)(ctx); 31 | 32 | function compose(middleware) { 33 | return function(context) { 34 | // 从第一个中间件 调起 35 | dispatch(0); 36 | 37 | /** 38 | * 调用指定 index 的中间件,为其传入 next 参数为下一个中间件的 dispatch 39 | * @param {Number} i 中间件索引 40 | * @return {Promise} resolve 后意味着上一个中间件 next() 后的代码可以继续执行 41 | */ 42 | function dispatch(i) { 43 | const fn = middleware[i]; 44 | if (i === middleware.length) { 45 | return Promise.resolve(); 46 | } 47 | try { 48 | // 当程序执行到await next 进入下一个中间件的调用 49 | // 当调用当前中间件,next参数设置为下一个中间件的dispatch 50 | const ret = fn(context, dispatch.bind(null, i + 1)); 51 | // 将本次调用的结果返还给上一个 中间件 也就是 await next() 52 | return Promise.resolve(ret); 53 | } catch (error) { 54 | return Promise.reject(error); 55 | } 56 | } 57 | }; 58 | } 59 | 60 | function compose1(middleware) { 61 | return function(context) { 62 | // 默认从第一个开始 63 | dispatch(0); 64 | /** 65 | * 调用对应 索引的中间件,为其传入 next,参数作为下一次的dispatch 66 | * @param {Number} i 中间件索引 67 | * @return {Promise} resolve后 上一个中间件的next() 之后的代码可以执行 68 | */ 69 | function dispatch(i) { 70 | const fn = middleware[i]; 71 | // 根据索引 取到对应的中间件函数 72 | if (i === middleware.length) { 73 | return Promise.resolve(); 74 | } 75 | try { 76 | // 调用当前中间件,并把下一次中间件的调用 函数传给 next函数 77 | const ret = fn(context, dispatch.bind(null, i + 1)); 78 | // 将本次调用的结果返还给上一个 中间件 也就是 await next() 79 | return Promise.resolve(ret); 80 | } catch (error) { 81 | return Promise.reject(error); 82 | } 83 | } 84 | }; 85 | } 86 | 87 | function compose2(middleware) { 88 | return function(context) { 89 | // 默认从第一个开始 90 | dispatch(0); 91 | function dispatch(i) { 92 | const fn = middleware[i]; 93 | if (i === middleware.length) { 94 | return Promise.resolve(); 95 | } 96 | try { 97 | const ret = fn(context, dispatch.bind(null, i + 1)); 98 | return Promise.resolve(ret); 99 | } catch (error) { 100 | return Promise.reject(error); 101 | } 102 | } 103 | }; 104 | } 105 | 106 | function compose3(middleware) { 107 | return function(context) { 108 | dispatch(0); 109 | function dispatch(i) { 110 | const fn = middleware[i]; 111 | if (i === middleware.length) { 112 | return Promise.resolve(); 113 | } 114 | try { 115 | const ret = fn(context, dispatch.bind(null, i + 1)); 116 | return Promise.resolve(ret); 117 | } catch (error) { 118 | return Promise.reject(error); 119 | } 120 | } 121 | }; 122 | } 123 | 124 | compose3(middleware)(ctx); 125 | 126 | function compose4(middleware) { 127 | return function temp(ctx) { 128 | dispatch(0); 129 | function dispatch(i) { 130 | const fn = middleware[i]; 131 | if (i === middleware.length) { 132 | return Promise.resolve(); 133 | } 134 | try { 135 | const ret = fn(ctx, dispatch.bind(null, i + 1)); 136 | return Promise.resolve(ret); 137 | } catch (error) { 138 | return Promise.reject(error); 139 | } 140 | } 141 | }; 142 | } 143 | 144 | -------------------------------------------------------------------------------- /src/Promise/myPromise.js: -------------------------------------------------------------------------------- 1 | const PENDIND = 'pending'; // 进行中 2 | const FULFILLED = 'fulfilled'; // 成功 3 | const REJECTED = 'rejected'; // 失败 4 | 5 | class MyPromise { 6 | constructor(exector) { 7 | try { 8 | exector(this.resolve, this.reject); 9 | } catch (error) { 10 | this.reject(error); 11 | } 12 | } 13 | status = PENDIND // 初始状态 14 | value = undefined // 成功回调的值 15 | reason = undefined // 失败回调的原因 16 | successCallback = [] // 成功回调的数组 17 | failCallback = [] // 失败回调的数组 18 | resolve = value => { 19 | if (this.status !== PENDIND) return; 20 | this.status = FULFILLED; 21 | this.value = value; 22 | // this.successCallback && this.successCallback(this.value); 23 | while (this.successCallback.length) this.successCallback.shift()(); 24 | } 25 | reject = reason => { 26 | if (this.status !== PENDIND) return; 27 | this.status = REJECTED; 28 | this.reason = reason; 29 | // this.failCallback && this.failCallback(this.reason); 30 | while (this.failCallback.length) this.failCallback.shift()(); 31 | } 32 | then(successCallback, failCallback) { 33 | successCallback = successCallback ? successCallback : value => value; 34 | failCallback = failCallback ? failCallback : reason => { throw reason; }; 35 | const promise2 = new MyPromise((resolve, reject) => { 36 | if (this.status === FULFILLED) { 37 | // 异步 获取promise2 38 | setTimeout(() => { 39 | try { 40 | const x = successCallback(this.value); 41 | // 将上一个then的返回值传递给下一个then的回调 42 | // 判断x是普通值还是promise实例 43 | // 如果是普通值直接调用resolve返回 44 | // 如果是promise实例 我们要拿到promise实例的值 传递给下一个then 45 | resolvePromise(promise2, x, resolve, reject); 46 | } catch (error) { 47 | reject(error); 48 | } 49 | }, 0); 50 | } else if (this.status === REJECTED) { 51 | // 异步 获取promise2 52 | setTimeout(() => { 53 | try { 54 | const x = failCallback(this.reason); 55 | // 将上一个then的返回值传递给下一个then的回调 56 | // 判断x是普通值还是promise实例 57 | // 如果是普通值直接调用resolve返回 58 | // 如果是promise实例 我们要拿到promise实例的值 传递给下一个then 59 | resolvePromise(promise2, x, resolve, reject); 60 | } catch (error) { 61 | reject(error); 62 | } 63 | }, 0); 64 | } else { 65 | this.successCallback.push(() => { 66 | setTimeout(() => { 67 | try { 68 | const x = successCallback(this.value); 69 | // 将上一个then的返回值传递给下一个then的回调 70 | // 判断x是普通值还是promise实例 71 | // 如果是普通值直接调用resolve返回 72 | // 如果是promise实例 我们要拿到promise实例的值 传递给下一个then 73 | resolvePromise(promise2, x, resolve, reject); 74 | } catch (error) { 75 | reject(error); 76 | } 77 | }, 0); 78 | }); 79 | this.failCallback.push(() => { 80 | setTimeout(() => { 81 | try { 82 | const x = failCallback(this.reason); 83 | // 将上一个then的返回值传递给下一个then的回调 84 | // 判断x是普通值还是promise实例 85 | // 如果是普通值直接调用resolve返回 86 | // 如果是promise实例 我们要拿到promise实例的值 传递给下一个then 87 | resolvePromise(promise2, x, resolve, reject); 88 | } catch (error) { 89 | reject(error); 90 | } 91 | }, 0); 92 | }); 93 | } 94 | }); 95 | // 实现链式调用 96 | return promise2; 97 | } 98 | finally(callback) { 99 | return this.then(value => { 100 | return MyPromise.resolve(callback()).then(() => value); 101 | }, error => { 102 | return MyPromise.resolve(callback()).then(() => { throw error; }); 103 | }); 104 | } 105 | catch(failCallback) { 106 | return this.then(undefined, failCallback); 107 | } 108 | static all(array) { 109 | const result = []; 110 | let index = 0; 111 | return new MyPromise((resolve, reject) => { 112 | function addData(i, value) { 113 | result[i] = value; 114 | // 有异步代码 所以这里要等待 115 | index++; 116 | if (index === array.length) { 117 | resolve(result); 118 | } 119 | } 120 | for (let i = 0; i < array.length; i++) { 121 | const current = array[i]; 122 | if (current instanceof MyPromise) { 123 | // promise 实例 124 | current.then(value => addData(i, value), reject); 125 | } else { 126 | // 普通值 127 | addData(i, array[i]); 128 | } 129 | } 130 | }); 131 | } 132 | static resolve(value) { 133 | if (value instanceof MyPromise) return value; 134 | return new MyPromise(resolve => resolve(value)); 135 | } 136 | } 137 | 138 | function resolvePromise(promise2, x, resolve, reject) { 139 | // 判断是否在then中返回了同一个 promise 实例 140 | if (promise2 === x) { 141 | return reject(new TypeError('then方法不能自己返回自己')); 142 | } 143 | if (x instanceof MyPromise) { 144 | // x.then(value => resolve(value), reason => reject(reason)); 145 | x.then(resolve, reject); 146 | } else { 147 | // 普通值 148 | resolve(x); 149 | } 150 | } 151 | 152 | module.exports = MyPromise; 153 | -------------------------------------------------------------------------------- /.eslintcache: -------------------------------------------------------------------------------- 1 | [{"/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/1.stack/1.删除最外层的括号.js":"1","/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/1.stack/10.用队列实现栈.js":"2","/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/1.stack/11.用栈操作构建数组.js":"3","/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/1.stack/12.包含min函数的栈.js":"4","/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/1.stack/13.栈的最小值.js":"5","/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/1.stack/14.最小栈.js":"6","/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/1.stack/15.比较含退格的字符串.js":"7","/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/1.stack/16.整理字符串.js":"8","/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/1.stack/17.滑动窗口最大的值.js":"9","/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/1.stack/2.用两个栈实现队列.js":"10","/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/1.stack/3.有效的括号.js":"11","/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/1.stack/4.最近的请求次数.js":"12","/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/1.stack/5.化栈为队.js":"13","/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/1.stack/6..删除字符串中的所有相邻重复项.js":"14","/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/1.stack/7.棒球比赛.js":"15","/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/1.stack/8.文件夹操作日志搜索器.js":"16","/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/1.stack/9.下一个更大元素.js":"17","/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/2.queue/1.最近的请求次数.js":"18","/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/2.queue/2.滑动窗口最大的值.js":"19","/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/3.string/1.有效括号.js":"20","/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/3.string/10.左旋转字符串.js":"21","/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/3.string/11.字符串压缩.js":"22","/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/3.string/12.匹配字符串中的数字.js":"23","/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/3.string/13.字符串中唯一字符.js":"24","/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/3.string/14.翻转字符串中的单词.js":"25","/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/3.string/15.判定是否互为字符重排.js":"26","/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/3.string/16.字符串相加.js":"27","/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/3.string/2.最长公共前缀.js":"28","/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/3.string/3.罗马数字转整数.js":"29","/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/3.string/4.实现strStr().js":"30","/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/3.string/5.外观数列.js":"31","/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/3.string/6.最后一个单词的长度.js":"32","/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/3.string/7.验证回文串.js":"33","/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/3.string/8.二进制和.js":"34","/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/3.string/9.翻转字符串.js":"35","/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/4.array/1.两数之和.js":"36","/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/4.array/10.合并两个有序数组.js":"37","/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/4.array/11.买卖股票的最佳时机2.js":"38","/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/4.array/12.数组中重复的数字.js":"39","/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/4.array/13.多数元素.js":"40","/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/4.array/14.杨辉三角.js":"41","/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/4.array/15.两数之和.js":"42","/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/4.array/16.判定字符是否唯一.js":"43","/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/4.array/17.存在重复元素.js":"44","/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/4.array/18.顺时针打印矩阵.js":"45","/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/4.array/2.删除有序数组的重复项.js":"46","/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/4.array/3.移出元素.js":"47","/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/4.array/4.搜索插入位置.js":"48","/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/4.array/5.合并排序的数组.js":"49","/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/4.array/6.买卖股票的最佳时机.js":"50","/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/4.array/7.最大子序的和.js":"51","/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/4.array/8.移动零.js":"52","/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/4.array/9.加一.js":"53"},{"size":534,"mtime":1623223473261,"results":"54","hashOfConfig":"55"},{"size":866,"mtime":1623223258340,"results":"56","hashOfConfig":"55"},{"size":924,"mtime":1623223258340,"results":"57","hashOfConfig":"55"},{"size":694,"mtime":1623223258340,"results":"58","hashOfConfig":"55"},{"size":700,"mtime":1623223258340,"results":"59","hashOfConfig":"55"},{"size":708,"mtime":1623223258340,"results":"60","hashOfConfig":"55"},{"size":463,"mtime":1623223258340,"results":"61","hashOfConfig":"55"},{"size":1213,"mtime":1623223258340,"results":"62","hashOfConfig":"55"},{"size":684,"mtime":1623223428777,"results":"63","hashOfConfig":"55"},{"size":707,"mtime":1623223258340,"results":"64","hashOfConfig":"55"},{"size":584,"mtime":1623223422846,"results":"65","hashOfConfig":"55"},{"size":404,"mtime":1623223258340,"results":"66","hashOfConfig":"55"},{"size":860,"mtime":1623223258340,"results":"67","hashOfConfig":"55"},{"size":285,"mtime":1623223258340,"results":"68","hashOfConfig":"55"},{"size":518,"mtime":1623223258340,"results":"69","hashOfConfig":"55"},{"size":395,"mtime":1623223258340,"results":"70","hashOfConfig":"55"},{"size":1359,"mtime":1623223258340,"results":"71","hashOfConfig":"55"},{"size":404,"mtime":1623223258340,"results":"72","hashOfConfig":"55"},{"size":684,"mtime":1623223412634,"results":"73","hashOfConfig":"55"},{"size":584,"mtime":1623223404749,"results":"74","hashOfConfig":"55"},{"size":261,"mtime":1623223258340,"results":"75","hashOfConfig":"55"},{"size":828,"mtime":1623223331979,"results":"76","hashOfConfig":"55"},{"size":261,"mtime":1623223258340,"results":"77","hashOfConfig":"55"},{"size":431,"mtime":1623223258340,"results":"78","hashOfConfig":"55"},{"size":217,"mtime":1623223258340,"results":"79","hashOfConfig":"55"},{"size":356,"mtime":1623223258340,"results":"80","hashOfConfig":"55"},{"size":747,"mtime":1623223363594,"results":"81","hashOfConfig":"55"},{"size":495,"mtime":1623223258340,"results":"82","hashOfConfig":"55"},{"size":535,"mtime":1623223258340,"results":"83","hashOfConfig":"55"},{"size":424,"mtime":1623223258340,"results":"84","hashOfConfig":"55"},{"size":260,"mtime":1623223258340,"results":"85","hashOfConfig":"55"},{"size":233,"mtime":1623223258340,"results":"86","hashOfConfig":"55"},{"size":358,"mtime":1623223258341,"results":"87","hashOfConfig":"55"},{"size":276,"mtime":1623223258341,"results":"88","hashOfConfig":"55"},{"size":303,"mtime":1623223258340,"results":"89","hashOfConfig":"55"},{"size":312,"mtime":1623223258341,"results":"90","hashOfConfig":"55"},{"size":330,"mtime":1623223258340,"results":"91","hashOfConfig":"55"},{"size":261,"mtime":1623223258340,"results":"92","hashOfConfig":"55"},{"size":284,"mtime":1623223258341,"results":"93","hashOfConfig":"55"},{"size":470,"mtime":1623223258341,"results":"94","hashOfConfig":"55"},{"size":498,"mtime":1623223258341,"results":"95","hashOfConfig":"55"},{"size":597,"mtime":1623223258341,"results":"96","hashOfConfig":"55"},{"size":228,"mtime":1623223258341,"results":"97","hashOfConfig":"55"},{"size":239,"mtime":1623223258341,"results":"98","hashOfConfig":"55"},{"size":2194,"mtime":1623223258341,"results":"99","hashOfConfig":"55"},{"size":247,"mtime":1623223258341,"results":"100","hashOfConfig":"55"},{"size":261,"mtime":1623223258341,"results":"101","hashOfConfig":"55"},{"size":248,"mtime":1623223258341,"results":"102","hashOfConfig":"55"},{"size":308,"mtime":1623223258341,"results":"103","hashOfConfig":"55"},{"size":272,"mtime":1623223258341,"results":"104","hashOfConfig":"55"},{"size":1196,"mtime":1623223342271,"results":"105","hashOfConfig":"55"},{"size":323,"mtime":1623223258342,"results":"106","hashOfConfig":"55"},{"size":337,"mtime":1623223307321,"results":"107","hashOfConfig":"55"},{"filePath":"108","messages":"109","errorCount":0,"warningCount":3,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},"1xxgoy7",{"filePath":"110","messages":"111","errorCount":0,"warningCount":4,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"112","messages":"113","errorCount":0,"warningCount":3,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"114","messages":"115","errorCount":0,"warningCount":3,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"116","messages":"117","errorCount":0,"warningCount":3,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"118","messages":"119","errorCount":0,"warningCount":3,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"120","messages":"121","errorCount":0,"warningCount":3,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"122","messages":"123","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"124","messages":"125","errorCount":0,"warningCount":3,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"126","messages":"127","errorCount":0,"warningCount":2,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"128","messages":"129","errorCount":0,"warningCount":2,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"130","messages":"131","errorCount":0,"warningCount":2,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"132","messages":"133","errorCount":0,"warningCount":4,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"134","messages":"135","errorCount":0,"warningCount":3,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"136","messages":"137","errorCount":0,"warningCount":2,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"138","messages":"139","errorCount":0,"warningCount":2,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"140","messages":"141","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"142","messages":"143","errorCount":0,"warningCount":2,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"144","messages":"145","errorCount":0,"warningCount":3,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"146","messages":"147","errorCount":0,"warningCount":2,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"148","messages":"149","errorCount":0,"warningCount":3,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"150","messages":"151","errorCount":0,"warningCount":6,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"152","messages":"153","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"154","messages":"155","errorCount":0,"warningCount":2,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"156","messages":"157","errorCount":0,"warningCount":2,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"158","messages":"159","errorCount":0,"warningCount":3,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"160","messages":"161","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"162","messages":"163","errorCount":0,"warningCount":2,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"164","messages":"165","errorCount":0,"warningCount":2,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"166","messages":"167","errorCount":0,"warningCount":3,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"168","messages":"169","errorCount":0,"warningCount":2,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"170","messages":"171","errorCount":0,"warningCount":2,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"172","messages":"173","errorCount":0,"warningCount":2,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"174","messages":"175","errorCount":0,"warningCount":3,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"176","messages":"177","errorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"178","messages":"179","errorCount":0,"warningCount":3,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"180","messages":"181","errorCount":0,"warningCount":4,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"182","messages":"183","errorCount":0,"warningCount":2,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"184","messages":"185","errorCount":0,"warningCount":2,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"186","messages":"187","errorCount":0,"warningCount":2,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"188","messages":"189","errorCount":0,"warningCount":2,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"190","messages":"191","errorCount":0,"warningCount":3,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"192","messages":"193","errorCount":0,"warningCount":2,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"194","messages":"195","errorCount":0,"warningCount":2,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"196","messages":"197","errorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"198","messages":"199","errorCount":0,"warningCount":2,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"200","messages":"201","errorCount":0,"warningCount":3,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"202","messages":"203","errorCount":0,"warningCount":3,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"204","messages":"205","errorCount":0,"warningCount":4,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"206","messages":"207","errorCount":0,"warningCount":2,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"208","messages":"209","errorCount":0,"warningCount":4,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"210","messages":"211","errorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"212","messages":"213","errorCount":0,"warningCount":2,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},"/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/1.stack/1.删除最外层的括号.js",["214","215","216"],"/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/1.stack/10.用队列实现栈.js",["217","218","219","220"],"/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/1.stack/11.用栈操作构建数组.js",["221","222","223"],"/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/1.stack/12.包含min函数的栈.js",["224","225","226"],"/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/1.stack/13.栈的最小值.js",["227","228","229"],"/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/1.stack/14.最小栈.js",["230","231","232"],"/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/1.stack/15.比较含退格的字符串.js",["233","234","235"],"/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/1.stack/16.整理字符串.js",[],"/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/1.stack/17.滑动窗口最大的值.js",["236","237","238"],"/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/1.stack/2.用两个栈实现队列.js",["239","240"],"/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/1.stack/3.有效的括号.js",["241","242"],"/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/1.stack/4.最近的请求次数.js",["243","244"],"/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/1.stack/5.化栈为队.js",["245","246","247","248"],"/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/1.stack/6..删除字符串中的所有相邻重复项.js",["249","250","251"],"/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/1.stack/7.棒球比赛.js",["252","253"],"/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/1.stack/8.文件夹操作日志搜索器.js",["254","255"],"/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/1.stack/9.下一个更大元素.js",[],"/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/2.queue/1.最近的请求次数.js",["256","257"],"/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/2.queue/2.滑动窗口最大的值.js",["258","259","260"],"/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/3.string/1.有效括号.js",["261","262"],"/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/3.string/10.左旋转字符串.js",["263","264","265"],"/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/3.string/11.字符串压缩.js",["266","267","268","269","270","271"],"/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/3.string/12.匹配字符串中的数字.js",[],"/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/3.string/13.字符串中唯一字符.js",["272","273"],"/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/3.string/14.翻转字符串中的单词.js",["274","275"],"/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/3.string/15.判定是否互为字符重排.js",["276","277","278"],"/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/3.string/16.字符串相加.js",[],"/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/3.string/2.最长公共前缀.js",["279","280"],"/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/3.string/3.罗马数字转整数.js",["281","282"],"/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/3.string/4.实现strStr().js",["283","284","285"],"/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/3.string/5.外观数列.js",["286","287"],"/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/3.string/6.最后一个单词的长度.js",["288","289"],"/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/3.string/7.验证回文串.js",["290","291"],"/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/3.string/8.二进制和.js",["292","293","294"],"/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/3.string/9.翻转字符串.js",["295"],"/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/4.array/1.两数之和.js",["296","297","298"],"/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/4.array/10.合并两个有序数组.js",["299","300","301","302"],"/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/4.array/11.买卖股票的最佳时机2.js",["303","304"],"/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/4.array/12.数组中重复的数字.js",["305","306"],"/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/4.array/13.多数元素.js",["307","308"],"/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/4.array/14.杨辉三角.js",["309","310"],"/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/4.array/15.两数之和.js",["311","312","313"],"/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/4.array/16.判定字符是否唯一.js",["314","315"],"/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/4.array/17.存在重复元素.js",["316","317"],"/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/4.array/18.顺时针打印矩阵.js",["318"],"/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/4.array/2.删除有序数组的重复项.js",["319","320"],"/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/4.array/3.移出元素.js",["321","322","323"],"/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/4.array/4.搜索插入位置.js",["324","325","326"],"/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/4.array/5.合并排序的数组.js",["327","328","329","330"],"/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/4.array/6.买卖股票的最佳时机.js",["331","332"],"/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/4.array/7.最大子序的和.js",["333","334","335","336"],"/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/4.array/8.移动零.js",["337"],"/Users/jimengbo/Desktop/learn/leetcode-js-roadmap/src/4.array/9.加一.js",["338","339"],{"ruleId":"340","severity":1,"message":"341","line":1,"column":1,"nodeType":"342","endLine":4,"endColumn":4},{"ruleId":"343","severity":1,"message":"344","line":2,"column":null,"nodeType":"342","endLine":2,"endColumn":null},{"ruleId":"345","severity":1,"message":"346","line":3,"column":null,"nodeType":"342","endLine":3,"endColumn":null},{"ruleId":"343","severity":1,"message":"347","line":10,"column":null,"nodeType":"342","endLine":10,"endColumn":null},{"ruleId":"345","severity":1,"message":"346","line":19,"column":null,"nodeType":"342","endLine":19,"endColumn":null},{"ruleId":"345","severity":1,"message":"346","line":27,"column":null,"nodeType":"342","endLine":27,"endColumn":null},{"ruleId":"345","severity":1,"message":"346","line":35,"column":null,"nodeType":"342","endLine":35,"endColumn":null},{"ruleId":"343","severity":1,"message":"348","line":2,"column":null,"nodeType":"342","endLine":2,"endColumn":null},{"ruleId":"343","severity":1,"message":"349","line":3,"column":null,"nodeType":"342","endLine":3,"endColumn":null},{"ruleId":"345","severity":1,"message":"346","line":4,"column":null,"nodeType":"342","endLine":4,"endColumn":null},{"ruleId":"343","severity":1,"message":"347","line":9,"column":null,"nodeType":"342","endLine":9,"endColumn":null},{"ruleId":"345","severity":1,"message":"346","line":24,"column":null,"nodeType":"342","endLine":24,"endColumn":null},{"ruleId":"345","severity":1,"message":"346","line":31,"column":null,"nodeType":"342","endLine":31,"endColumn":null},{"ruleId":"343","severity":1,"message":"347","line":9,"column":null,"nodeType":"342","endLine":9,"endColumn":null},{"ruleId":"345","severity":1,"message":"346","line":24,"column":null,"nodeType":"342","endLine":24,"endColumn":null},{"ruleId":"345","severity":1,"message":"346","line":31,"column":null,"nodeType":"342","endLine":31,"endColumn":null},{"ruleId":"343","severity":1,"message":"350","line":9,"column":null,"nodeType":"342","endLine":9,"endColumn":null},{"ruleId":"345","severity":1,"message":"346","line":24,"column":null,"nodeType":"342","endLine":24,"endColumn":null},{"ruleId":"345","severity":1,"message":"346","line":31,"column":null,"nodeType":"342","endLine":31,"endColumn":null},{"ruleId":"343","severity":1,"message":"351","line":2,"column":null,"nodeType":"342","endLine":2,"endColumn":null},{"ruleId":"343","severity":1,"message":"352","line":3,"column":null,"nodeType":"342","endLine":3,"endColumn":null},{"ruleId":"345","severity":1,"message":"346","line":4,"column":null,"nodeType":"342","endLine":4,"endColumn":null},{"ruleId":"343","severity":1,"message":"353","line":2,"column":null,"nodeType":"342","endLine":2,"endColumn":null},{"ruleId":"343","severity":1,"message":"354","line":3,"column":null,"nodeType":"342","endLine":3,"endColumn":null},{"ruleId":"345","severity":1,"message":"346","line":4,"column":null,"nodeType":"342","endLine":4,"endColumn":null},{"ruleId":"343","severity":1,"message":"355","line":8,"column":null,"nodeType":"342","endLine":8,"endColumn":null},{"ruleId":"345","severity":1,"message":"346","line":16,"column":null,"nodeType":"342","endLine":16,"endColumn":null},{"ruleId":"343","severity":1,"message":"351","line":3,"column":null,"nodeType":"342","endLine":3,"endColumn":null},{"ruleId":"345","severity":1,"message":"346","line":4,"column":null,"nodeType":"342","endLine":4,"endColumn":null},{"ruleId":"343","severity":1,"message":"352","line":6,"column":null,"nodeType":"342","endLine":6,"endColumn":null},{"ruleId":"345","severity":1,"message":"346","line":7,"column":null,"nodeType":"342","endLine":7,"endColumn":null},{"ruleId":"343","severity":1,"message":"347","line":10,"column":null,"nodeType":"342","endLine":10,"endColumn":null},{"ruleId":"345","severity":1,"message":"346","line":19,"column":null,"nodeType":"342","endLine":19,"endColumn":null},{"ruleId":"345","severity":1,"message":"346","line":27,"column":null,"nodeType":"342","endLine":27,"endColumn":null},{"ruleId":"345","severity":1,"message":"346","line":35,"column":null,"nodeType":"342","endLine":35,"endColumn":null},{"ruleId":"340","severity":1,"message":"341","line":1,"column":1,"nodeType":"342","endLine":4,"endColumn":4},{"ruleId":"343","severity":1,"message":"344","line":2,"column":null,"nodeType":"342","endLine":2,"endColumn":null},{"ruleId":"345","severity":1,"message":"346","line":3,"column":null,"nodeType":"342","endLine":3,"endColumn":null},{"ruleId":"343","severity":1,"message":"356","line":2,"column":null,"nodeType":"342","endLine":2,"endColumn":null},{"ruleId":"345","severity":1,"message":"346","line":3,"column":null,"nodeType":"342","endLine":3,"endColumn":null},{"ruleId":"343","severity":1,"message":"357","line":2,"column":null,"nodeType":"342","endLine":2,"endColumn":null},{"ruleId":"345","severity":1,"message":"346","line":3,"column":null,"nodeType":"342","endLine":3,"endColumn":null},{"ruleId":"343","severity":1,"message":"352","line":6,"column":null,"nodeType":"342","endLine":6,"endColumn":null},{"ruleId":"345","severity":1,"message":"346","line":7,"column":null,"nodeType":"342","endLine":7,"endColumn":null},{"ruleId":"343","severity":1,"message":"353","line":2,"column":null,"nodeType":"342","endLine":2,"endColumn":null},{"ruleId":"343","severity":1,"message":"354","line":3,"column":null,"nodeType":"342","endLine":3,"endColumn":null},{"ruleId":"345","severity":1,"message":"346","line":4,"column":null,"nodeType":"342","endLine":4,"endColumn":null},{"ruleId":"343","severity":1,"message":"351","line":3,"column":null,"nodeType":"342","endLine":3,"endColumn":null},{"ruleId":"345","severity":1,"message":"346","line":4,"column":null,"nodeType":"342","endLine":4,"endColumn":null},{"ruleId":"343","severity":1,"message":"351","line":2,"column":null,"nodeType":"342","endLine":2,"endColumn":null},{"ruleId":"343","severity":1,"message":"349","line":3,"column":null,"nodeType":"342","endLine":3,"endColumn":null},{"ruleId":"345","severity":1,"message":"346","line":4,"column":null,"nodeType":"342","endLine":4,"endColumn":null},{"ruleId":"340","severity":1,"message":"341","line":1,"column":1,"nodeType":"342","endLine":4,"endColumn":4},{"ruleId":"343","severity":1,"message":"344","line":2,"column":null,"nodeType":"342","endLine":2,"endColumn":null},{"ruleId":"345","severity":1,"message":"346","line":3,"column":null,"nodeType":"342","endLine":3,"endColumn":null},{"ruleId":"340","severity":1,"message":"341","line":25,"column":1,"nodeType":"342","endLine":28,"endColumn":4},{"ruleId":"343","severity":1,"message":"344","line":26,"column":null,"nodeType":"342","endLine":26,"endColumn":null},{"ruleId":"345","severity":1,"message":"346","line":27,"column":null,"nodeType":"342","endLine":27,"endColumn":null},{"ruleId":"343","severity":1,"message":"351","line":2,"column":null,"nodeType":"342","endLine":2,"endColumn":null},{"ruleId":"345","severity":1,"message":"346","line":3,"column":null,"nodeType":"342","endLine":3,"endColumn":null},{"ruleId":"343","severity":1,"message":"351","line":2,"column":null,"nodeType":"342","endLine":2,"endColumn":null},{"ruleId":"345","severity":1,"message":"346","line":3,"column":null,"nodeType":"342","endLine":3,"endColumn":null},{"ruleId":"343","severity":1,"message":"358","line":2,"column":null,"nodeType":"342","endLine":2,"endColumn":null},{"ruleId":"343","severity":1,"message":"359","line":3,"column":null,"nodeType":"342","endLine":3,"endColumn":null},{"ruleId":"345","severity":1,"message":"346","line":4,"column":null,"nodeType":"342","endLine":4,"endColumn":null},{"ruleId":"343","severity":1,"message":"360","line":2,"column":null,"nodeType":"342","endLine":2,"endColumn":null},{"ruleId":"345","severity":1,"message":"346","line":3,"column":null,"nodeType":"342","endLine":3,"endColumn":null},{"ruleId":"343","severity":1,"message":"351","line":2,"column":null,"nodeType":"342","endLine":2,"endColumn":null},{"ruleId":"345","severity":1,"message":"346","line":3,"column":null,"nodeType":"342","endLine":3,"endColumn":null},{"ruleId":"343","severity":1,"message":"361","line":2,"column":null,"nodeType":"342","endLine":2,"endColumn":null},{"ruleId":"343","severity":1,"message":"362","line":3,"column":null,"nodeType":"342","endLine":3,"endColumn":null},{"ruleId":"345","severity":1,"message":"346","line":4,"column":null,"nodeType":"342","endLine":4,"endColumn":null},{"ruleId":"343","severity":1,"message":"349","line":2,"column":null,"nodeType":"342","endLine":2,"endColumn":null},{"ruleId":"345","severity":1,"message":"346","line":3,"column":null,"nodeType":"342","endLine":3,"endColumn":null},{"ruleId":"343","severity":1,"message":"351","line":2,"column":null,"nodeType":"342","endLine":2,"endColumn":null},{"ruleId":"345","severity":1,"message":"346","line":3,"column":null,"nodeType":"342","endLine":3,"endColumn":null},{"ruleId":"343","severity":1,"message":"351","line":2,"column":null,"nodeType":"342","endLine":2,"endColumn":null},{"ruleId":"345","severity":1,"message":"346","line":3,"column":null,"nodeType":"342","endLine":3,"endColumn":null},{"ruleId":"343","severity":1,"message":"363","line":2,"column":null,"nodeType":"342","endLine":2,"endColumn":null},{"ruleId":"343","severity":1,"message":"364","line":3,"column":null,"nodeType":"342","endLine":3,"endColumn":null},{"ruleId":"345","severity":1,"message":"346","line":4,"column":null,"nodeType":"342","endLine":4,"endColumn":null},{"ruleId":"343","severity":1,"message":"351","line":2,"column":null,"nodeType":"342","endLine":2,"endColumn":null},{"ruleId":"343","severity":1,"message":"353","line":2,"column":null,"nodeType":"342","endLine":2,"endColumn":null},{"ruleId":"343","severity":1,"message":"348","line":3,"column":null,"nodeType":"342","endLine":3,"endColumn":null},{"ruleId":"345","severity":1,"message":"346","line":4,"column":null,"nodeType":"342","endLine":4,"endColumn":null},{"ruleId":"343","severity":1,"message":"365","line":2,"column":null,"nodeType":"342","endLine":2,"endColumn":null},{"ruleId":"343","severity":1,"message":"366","line":3,"column":null,"nodeType":"342","endLine":3,"endColumn":null},{"ruleId":"343","severity":1,"message":"367","line":4,"column":null,"nodeType":"342","endLine":4,"endColumn":null},{"ruleId":"343","severity":1,"message":"349","line":5,"column":null,"nodeType":"342","endLine":5,"endColumn":null},{"ruleId":"343","severity":1,"message":"368","line":2,"column":null,"nodeType":"342","endLine":2,"endColumn":null},{"ruleId":"345","severity":1,"message":"346","line":3,"column":null,"nodeType":"342","endLine":3,"endColumn":null},{"ruleId":"343","severity":1,"message":"353","line":2,"column":null,"nodeType":"342","endLine":2,"endColumn":null},{"ruleId":"345","severity":1,"message":"346","line":3,"column":null,"nodeType":"342","endLine":3,"endColumn":null},{"ruleId":"343","severity":1,"message":"353","line":2,"column":null,"nodeType":"342","endLine":2,"endColumn":null},{"ruleId":"345","severity":1,"message":"346","line":3,"column":null,"nodeType":"342","endLine":3,"endColumn":null},{"ruleId":"343","severity":1,"message":"369","line":2,"column":null,"nodeType":"342","endLine":2,"endColumn":null},{"ruleId":"345","severity":1,"message":"346","line":3,"column":null,"nodeType":"342","endLine":3,"endColumn":null},{"ruleId":"343","severity":1,"message":"370","line":2,"column":null,"nodeType":"342","endLine":2,"endColumn":null},{"ruleId":"343","severity":1,"message":"348","line":3,"column":null,"nodeType":"342","endLine":3,"endColumn":null},{"ruleId":"345","severity":1,"message":"346","line":4,"column":null,"nodeType":"342","endLine":4,"endColumn":null},{"ruleId":"343","severity":1,"message":"371","line":2,"column":null,"nodeType":"342","endLine":2,"endColumn":null},{"ruleId":"345","severity":1,"message":"346","line":3,"column":null,"nodeType":"342","endLine":3,"endColumn":null},{"ruleId":"343","severity":1,"message":"353","line":2,"column":null,"nodeType":"342","endLine":2,"endColumn":null},{"ruleId":"345","severity":1,"message":"346","line":3,"column":null,"nodeType":"342","endLine":3,"endColumn":null},{"ruleId":"372","severity":1,"message":"373","line":6,"column":1,"nodeType":"342","endLine":24,"endColumn":4},{"ruleId":"343","severity":1,"message":"353","line":2,"column":null,"nodeType":"342","endLine":2,"endColumn":null},{"ruleId":"345","severity":1,"message":"346","line":3,"column":null,"nodeType":"342","endLine":3,"endColumn":null},{"ruleId":"343","severity":1,"message":"353","line":2,"column":null,"nodeType":"342","endLine":2,"endColumn":null},{"ruleId":"343","severity":1,"message":"350","line":3,"column":null,"nodeType":"342","endLine":3,"endColumn":null},{"ruleId":"345","severity":1,"message":"346","line":4,"column":null,"nodeType":"342","endLine":4,"endColumn":null},{"ruleId":"343","severity":1,"message":"353","line":2,"column":null,"nodeType":"342","endLine":2,"endColumn":null},{"ruleId":"343","severity":1,"message":"348","line":3,"column":null,"nodeType":"342","endLine":3,"endColumn":null},{"ruleId":"345","severity":1,"message":"346","line":4,"column":null,"nodeType":"342","endLine":4,"endColumn":null},{"ruleId":"343","severity":1,"message":"374","line":2,"column":null,"nodeType":"342","endLine":2,"endColumn":null},{"ruleId":"343","severity":1,"message":"366","line":3,"column":null,"nodeType":"342","endLine":3,"endColumn":null},{"ruleId":"343","severity":1,"message":"375","line":4,"column":null,"nodeType":"342","endLine":4,"endColumn":null},{"ruleId":"343","severity":1,"message":"349","line":5,"column":null,"nodeType":"342","endLine":5,"endColumn":null},{"ruleId":"343","severity":1,"message":"368","line":2,"column":null,"nodeType":"342","endLine":2,"endColumn":null},{"ruleId":"345","severity":1,"message":"346","line":3,"column":null,"nodeType":"342","endLine":3,"endColumn":null},{"ruleId":"343","severity":1,"message":"353","line":2,"column":null,"nodeType":"342","endLine":2,"endColumn":null},{"ruleId":"345","severity":1,"message":"346","line":3,"column":null,"nodeType":"342","endLine":3,"endColumn":null},{"ruleId":"343","severity":1,"message":"353","line":28,"column":null,"nodeType":"342","endLine":28,"endColumn":null},{"ruleId":"345","severity":1,"message":"346","line":29,"column":null,"nodeType":"342","endLine":29,"endColumn":null},{"ruleId":"343","severity":1,"message":"353","line":2,"column":null,"nodeType":"342","endLine":2,"endColumn":null},{"ruleId":"343","severity":1,"message":"376","line":2,"column":null,"nodeType":"342","endLine":2,"endColumn":null},{"ruleId":"345","severity":1,"message":"346","line":3,"column":null,"nodeType":"342","endLine":3,"endColumn":null},"jsdoc/check-param-names","Expected @param names to be \"s\". Got \"S\".","Block","jsdoc/require-param-description","Missing JSDoc @param \"S\" description.","jsdoc/require-returns-description","Missing JSDoc @return description.","Missing JSDoc @param \"x\" description.","Missing JSDoc @param \"target\" description.","Missing JSDoc @param \"n\" description.","Missing JSDoc @param \"val\" description.","Missing JSDoc @param \"s\" description.","Missing JSDoc @param \"t\" description.","Missing JSDoc @param \"nums\" description.","Missing JSDoc @param \"k\" description.","Missing JSDoc @param \"value\" description.","Missing JSDoc @param \"ops\" description.","Missing JSDoc @param \"logs\" description.","Missing JSDoc @param \"s1\" description.","Missing JSDoc @param \"s2\" description.","Missing JSDoc @param \"strs\" description.","Missing JSDoc @param \"haystack\" description.","Missing JSDoc @param \"needle\" description.","Missing JSDoc @param \"a\" description.","Missing JSDoc @param \"b\" description.","Missing JSDoc @param \"nums1\" description.","Missing JSDoc @param \"m\" description.","Missing JSDoc @param \"nums2\" description.","Missing JSDoc @param \"prices\" description.","Missing JSDoc @param \"numRows\" description.","Missing JSDoc @param \"numbers\" description.","Missing JSDoc @param \"astr\" description.","jsdoc/require-param","Missing JSDoc @param \"matrix\" declaration.","Missing JSDoc @param \"A\" description.","Missing JSDoc @param \"B\" description.","Missing JSDoc @param \"digits\" description."] --------------------------------------------------------------------------------