数组
疾速排序
function quickSort(arr, left, right) { if (left >= right) return const base = arr[left] let p = left, q = right while (p < q) { while (arr[q] > base && q >= p) { q-- } while (arr[p] < base && p <= q) { p++ } const temp = arr[q] arr[q] = arr[p] arr[p] = temp } arr[p] = base quickSort(arr, left, p) quickSort(arr, p + 1, right)}
归并排序
function mergeSort(arr) { if (arr.length <= 1) return arr const mid = Math.floor(arr.length / 2) const left = arr.slice(0, mid) const right = arr.slice(mid) const leftArr = mergeSort(left) const rightArr = mergeSort(right) const result = [] while (leftArr.length > 0 && rightArr.length > 0) { if (leftArr[0] < rightArr[0]) { result.push(leftArr.shift()) } else { result.push(rightArr.shift()) } } return result.concat(leftArr).concat(rightArr)}
两数之和
var twoSum = function (nums, target) { let hash = {}; for (let i = 0; i < nums.length; i++) { if (hash[target - nums[i]] !== undefined) { return [i, hash[target - nums[i]]]; } hash[nums[i]] = i; } return []; };
三数之和
var threeSum = function(nums) { const len = nums.length; if(len < 3) return []; nums.sort((a, b) => a - b); const resSet = new Set(); for(let i = 0; i < len - 2; i++) { if(nums[i] > 0) break; let l = i + 1, r = len - 1; while(l < r) { const sum = nums[i] + nums[l] + nums[r]; if(sum < 0) { l++; continue }; if(sum > 0) { r--; continue }; resSet.add(`${nums[i]},${nums[l]},${nums[r]}`); l++; r--; } } return Array.from(resSet).map(i => i.split(","));};
二分查找
var search = function(nums, target) { let left = 0, right = nums.length - 1; // 应用左闭右闭区间 while (left <= right) { let mid = left + Math.floor((right - left)/2); if (nums[mid] > target) { right = mid - 1; // 去右面闭区间寻找 } else if (nums[mid] < target) { left = mid + 1; // 去右面闭区间寻找 } else { return mid; } } return -1;};
螺旋矩阵遍历
var generateMatrix = function(n) { let startX = startY = 0; // 起始地位 let loop = Math.floor(n/2); // 旋转圈数 let mid = Math.floor(n/2); // 两头地位 let offset = 1; // 管制每一层填充元素个数 let count = 1; // 更新填充数字 let res = new Array(n).fill(0).map(() => new Array(n).fill(0)); while (loop--) { let row = startX, col = startY; // 上行从左到右(左闭右开) for (; col < startY + n - offset; col++) { res[row][col] = count++; } // 右列从上到下(左闭右开) for (; row < startX + n - offset; row++) { res[row][col] = count++; } // 上行从右到左(左闭右开) for (; col > startX; col--) { res[row][col] = count++; } // 左列做下到上(左闭右开) for (; row > startY; row--) { res[row][col] = count++; } // 更新起始地位 startX++; startY++; // 更新offset offset += 2; } // 如果n为奇数的话,须要独自给矩阵最两头的地位赋值 if (n % 2 === 1) { res[mid][mid] = count; } return res;};
合并两个有序数组
var merge = function(nums1, m, nums2, n) { let p1 = m - 1, p2 = n - 1; let tail = m + n - 1; var cur; while (p1 >= 0 || p2 >= 0) { if (p1 === -1) { cur = nums2[p2--]; } else if (p2 === -1) { cur = nums1[p1--]; } else if (nums1[p1] > nums2[p2]) { cur = nums1[p1--]; } else { cur = nums2[p2--]; } nums1[tail--] = cur; }};
随机排序
function shuffle(arr) { var i, j, temp; for (i = arr.length - 1; i > 0; i--) { j = Math.floor(Math.random() * (i + 1)); temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; } return arr;}// 这个实现有问题 function shuffle(arr){ return arr.sort(function(){ return Math.random() - 0.5; });}
字符串
两数之和
var addStrings = function (num1, num2) { const result = [] let p = num1.length - 1 let q = num2.length - 1 let add = 0 while (p >= 0 || q >= 0 || add) { const x = p >= 0 ? Number(num1[p]) : 0 const y = q >= 0 ? Number(num2[q]) : 0 const sum = x + y + add result.unshift(sum % 10) add = Math.floor(sum / 10) p-- q-- } return result.join('')};
千分符格式化
var thousandSeparator = function(n) { let res = '' let count = 0 const str = n.toString() const len = str.length for(let i = len - 1; i >= 0; i--) { count++ if (count % 3 === 0 && i !== 0) { res = '.' + str[i] + res } else { res = str[i] + res } } return res};
无效括号
var isValid = function(s) { const n = s.length; if (n % 2 === 1) { return false; } const pairs = new Map([ [')', '('], [']', '['], ['}', '{'] ]); const stk = []; for (let ch of s){ if (pairs.has(ch)) { if (!stk.length || stk[stk.length - 1] !== pairs.get(ch)) { return false; } stk.pop(); } else { stk.push(ch); } }; return !stk.length;};
链表
反转链表
var reverseList = function(head) { let pre = null let cur = head while(cur !== null) { const temp = cur.next cur.next = pre pre = cur cur = temp } return pre};
删除链表倒数第N个结点
var removeNthFromEnd = function(head, n) { let ret = new ListNode() ret.next = head let p = ret, q = ret // p 先后退N while(n--) { p = p.next } // p 遍历到尾结点 while(p.next !== null) { p = p.next q = q.next } q.next = q.next.next return ret.next};
合并两个有序链表
var mergeTwoLists = function(l1, l2) { const prehead = new ListNode(-1); let prev = prehead; while (l1 != null && l2 != null) { if (l1.val <= l2.val) { prev.next = l1; l1 = l1.next; } else { prev.next = l2; l2 = l2.next; } prev = prev.next; } // 合并后 l1 和 l2 最多只有一个还未被合并完,咱们间接将链表开端指向未合并完的链表即可 prev.next = l1 === null ? l2 : l1; return prehead.next;};
二叉树
深度优先遍历(递归和迭代)
// 递归var preorderTraversal = function(root) { let res=[]; const dfs=function(root){ if(root===null)return ; //先序遍历所以从父节点开始 res.push(root.val); //递归左子树 dfs(root.left); //递归右子树 dfs(root.right); } //只应用一个参数 应用闭包进行存储后果 dfs(root); return res;};// 迭代var preorderTraversal = function(root, res = []) { if(!root) return res; const stack = [root]; let cur = null; while(stack.length) { cur = stack.pop(); res.push(cur.val); cur.right && stack.push(cur.right); cur.left && stack.push(cur.left); } return res;};
档次遍历
var levelOrder = function(root) { //二叉树的层序遍历 let res=[],queue=[]; queue.push(root); if(root===null){ return res; } while(queue.length!==0){ // 记录以后层级节点数 let length=queue.length; //寄存每一层的节点 let curLevel=[]; for(let i=0;i<length;i++){ let node=queue.shift(); curLevel.push(node.val); // 寄存以后层下一层的节点 node.left&&queue.push(node.left); node.right&&queue.push(node.right); } //把每一层的后果放到后果数组 res.push(curLevel); } return res;};
最大深度
var maxdepth = function(root) { if (!root) return root return 1 + math.max(maxdepth(root.left), maxdepth(root.right))};
最近公共先人
var lowestCommonAncestor = function(root, p, q) { // 应用递归的办法 // 须要从下到上,所以应用后序遍历 // 1. 确定递归的函数 const travelTree = function(root,p,q) { // 2. 确定递归终止条件 if(root === null || root === p||root === q) { return root; } // 3. 确定递归单层逻辑 let left = travelTree(root.left,p,q); let right = travelTree(root.right,p,q); if(left !== null&&right !== null) { return root; } if(left ===null) { return right; } return left; } return travelTree(root,p,q);};
对称二叉树
var isSymmetric = function(root) { //应用递归遍历左右子树 递归三部曲 // 1. 确定递归的参数 root.left root.right和返回值true false const compareNode=function(left,right){ //2. 确定终止条件 空的状况 if(left===null&&right!==null||left!==null&&right===null){ return false; }else if(left===null&&right===null){ return true; }else if(left.val!==right.val){ return false; } //3. 确定单层递归逻辑 let outSide=compareNode(left.left,right.right); let inSide=compareNode(left.right,right.left); return outSide&&inSide; } if(root===null){ return true; } return compareNode(root.left,root.right);};
动静布局
最长重复子数组
// 输出: A: [1,2,3,2,1] B: [3,2,1,4,7] 输入:3 解释: 长度最长的公共子数组是 [3, 2, 1] 。const findLength = (A, B) => { // A、B数组的长度 const [m, n] = [A.length, B.length]; // dp数组初始化,都初始化为0 const dp = new Array(m + 1).fill(0).map(x => new Array(n + 1).fill(0)); // 初始化最大长度为0 let res = 0; for (let i = 1; i <= m; i++) { for (let j = 1; j <= n; j++) { // 遇到A[i - 1] === B[j - 1],则更新dp数组 if (A[i - 1] === B[j - 1]) { dp[i][j] = dp[i - 1][j - 1] + 1; } // 更新res res = dp[i][j] > res ? dp[i][j] : res; } } // 遍历实现,返回res return res;};
最长公共子序列
// 输出:text1 = "abcde", text2 = "ace" 输入:3 解释:最长公共子序列是 "ace",它的长度为 3。const longestCommonSubsequence = (text1, text2) => { let dp = Array.from(Array(text1.length+1), () => Array(text2.length+1).fill(0)); for(let i = 1; i <= text1.length; i++) { for(let j = 1; j <= text2.length; j++) { if(text1[i-1] === text2[j-1]) { dp[i][j] = dp[i-1][j-1] +1;; } else { dp[i][j] = Math.max(dp[i-1][j], dp[i][j-1]) } } } return dp[text1.length][text2.length];};
最长间断递增序列
const findLengthOfLCIS = (nums) => { let dp = Array(nums.length).fill(1); for(let i = 0; i < nums.length - 1; i++) { if(nums[i+1] > nums[i]) { dp[i+1] = dp[i]+ 1; } } return Math.max(...dp);};
最大回文子串
var longestPalindrome = function (s) { const len = s.length if (len < 2) return s let max = 0 let str = s[0] const dp = Array.from(new Array(len), () => new Array(len)) for(let j=0; j< len; j++) { for(let i=0; i<j; i++) { dp[i][j] = s[i] === s[j] && (j - i < 3 || dp[i+1][j-1]) if(dp[i][j] && j -i + 1 > max) { max = j - i + 1 str = s.substring(i, j+1) } } } return str }
最长回文子序列
const longestPalindromeSubseq = (s) => { const strLen = s.length; let dp = Array.from(Array(strLen), () => Array(strLen).fill(0)); for(let i = 0; i < strLen; i++) { dp[i][i] = 1; } for(let i = strLen - 1; i >= 0; i--) { for(let j = i + 1; j < strLen; j++) { if(s[i] === s[j]) { dp[i][j] = dp[i+1][j-1] + 2; } else { dp[i][j] = Math.max(dp[i+1][j], dp[i][j-1]); } } } return dp[0][strLen - 1];};
无重复子数组最大长度 (滑动窗口)
function sub(arr) { let max = 0 let base = 0 const has = new Map() for(let i = 0; i < arr.length; i++) { const cur = arr[i] if (hash.hash(cur)) { base = Math.max(base, has.get(cur) + 1) } hast.set(cur, i) max = Math.max(max, i - base + 1) } return max}
子数组乘积最大
function largestSum(arr) { let max = Number.MIN_SAFE_INTEGER, fmin = arr[0], fmax= arr[0] for(let num of arr) { if (num < 0) { const temp = fmax fmax = fmin fmin = temp } fmin = Math.min(fmin*num, num) fmax = Math.max(fmax*num, num) max = Math.max(max, fmax) } return max}
最小费用
function minCount(days, cost) { const len = days.length let maxDay = days[len - 1], minDay = days[0] let dp = new Array(maxDay + 31).fill(0) for(let d = maxDay, i = len -1; d >= minDay; d-- ) { if (days[i] === d) { dp[d] = Math.min(dp[d + 1] + cost[0], dp[d+7] + cost[1], dp[d+30]+cost[2]) i-- } else { dp[d] = dp[d+1] } } return dp[minDay]}