# 数据结构与算法 ## 1. 链表 > **场景**:操作历史记录(浏览器前进后退)、LRU 缓存淘汰、撤销重做功能、音乐播放列表。 > **解决**:频繁插入/删除场景下数组性能差的问题,O(1) 插入删除。 ### 反转链表 ```js function reverseList(head) { let prev = null, curr = head; while (curr) { const next = curr.next; curr.next = prev; prev = curr; curr = next; } return prev; } ``` ### 环形链表判断 ```js function hasCycle(head) { let slow = head, fast = head; while (fast?.next) { slow = slow.next; fast = fast.next.next; if (slow === fast) return true; } return false; } ``` ### 合并有序链表 ```js function mergeTwoLists(l1, l2) { const dummy = { next: null }; let curr = dummy; while (l1 && l2) { if (l1.val <= l2.val) { curr.next = l1; l1 = l1.next; } else { curr.next = l2; l2 = l2.next; } curr = curr.next; } curr.next = l1 || l2; return dummy.next; } ``` --- ## 2. 二叉树 > **场景**:DOM 树遍历、文件目录结构、组织架构图、表达式解析、前端路由匹配。 > **解决**:层级数据的存储与高效查找,遍历、搜索与路径问题。 ### 遍历(前中后序) ```js // 前序:根-左-右 const preorder = (root, res = []) => { if (!root) return res; res.push(root.val); preorder(root.left, res); preorder(root.right, res); return res; }; // 中序:左-根-右 const inorder = (root, res = []) => { if (!root) return res; inorder(root.left, res); res.push(root.val); inorder(root.right, res); return res; }; // 后序:左-右-根 const postorder = (root, res = []) => { if (!root) return res; postorder(root.left, res); postorder(root.right, res); res.push(root.val); return res; }; ``` ### 求最大深度 ```js const maxDepth = root => { if (!root) return 0; return 1 + Math.max(maxDepth(root.left), maxDepth(root.right)); }; ``` ### 路径和 ```js function hasPathSum(root, targetSum) { if (!root) return false; if (!root.left && !root.right) return targetSum === root.val; return hasPathSum(root.left, targetSum - root.val) || hasPathSum(root.right, targetSum - root.val); } ``` --- ## 3. 栈与队列 > **场景**:栈用于括号匹配、撤销操作、函数调用栈;队列用于任务调度、消息队列、BFS 广度优先搜索。 > **解决**:先进后出/先进先出的数据操作顺序控制。 ### 用栈实现队列 ```js class MyQueue { constructor() { this.inStack = []; this.outStack = []; } push(x) { this.inStack.push(x); } pop() { if (!this.outStack.length) { while (this.inStack.length) this.outStack.push(this.inStack.pop()); } return this.outStack.pop(); } peek() { if (!this.outStack.length) { while (this.inStack.length) this.outStack.push(this.inStack.pop()); } return this.outStack[this.outStack.length - 1]; } empty() { return !this.inStack.length && !this.outStack.length; } } ``` ### 有效的括号 ```js function isValid(s) { const map = { ')': '(', ']': '[', '}': '{' }; const stack = []; for (const c of s) { if (map[c]) { if (stack.pop() !== map[c]) return false; } else { stack.push(c); } } return !stack.length; } ``` --- ## 4. 哈希表 > **场景**:快速查找(用户ID查询)、统计词频、数据去重、分组操作。 > **解决**:O(1) 时间复杂度的键值对存储和查找,避免线性遍历。 ### 两数之和 ```js function twoSum(nums, target) { const map = new Map(); for (let i = 0; i < nums.length; i++) { const diff = target - nums[i]; if (map.has(diff)) return [map.get(diff), i]; map.set(nums[i], i); } return []; } ``` ### 字母异位词分组 ```js function groupAnagrams(strs) { const map = new Map(); for (const s of strs) { const key = [...s].sort().join(''); map.set(key, (map.get(key) || []).concat(s)); } return [...map.values()]; } ``` --- ## 5. 排序算法 > **场景**:商品价格/销量排序、排行榜、数据可视化预处理。 > **解决**:无序数据有序化,理解分治思想(快排、归并)是算法基础。 ### 快速排序 ```js function quickSort(arr) { if (arr.length <= 1) return arr; const pivot = arr[Math.floor(arr.length / 2)]; const left = arr.filter(x => x < pivot); const middle = arr.filter(x => x === pivot); const right = arr.filter(x => x > pivot); return [...quickSort(left), ...middle, ...quickSort(right)]; } ``` ### 归并排序 ```js function mergeSort(arr) { if (arr.length <= 1) return arr; const mid = Math.floor(arr.length / 2); const left = mergeSort(arr.slice(0, mid)); const right = mergeSort(arr.slice(mid)); return merge(left, right); } function merge(left, right) { const result = []; let i = 0, j = 0; while (i < left.length && j < right.length) { result.push(left[i] < right[j] ? left[i++] : right[j++]); } return result.concat(left.slice(i), right.slice(j)); } ``` --- ## 6. 二分查找 > **场景**:有序列表快速定位(分页跳转)、版本号查找、IP 地址归属地查询、猜数字游戏。 > **解决**:在有序数据中 O(log n) 时间复杂度快速查找,比线性查找效率高很多。 ### 基础二分查找 ```js function binarySearch(arr, target) { let left = 0, right = arr.length - 1; while (left <= right) { const mid = Math.floor((left + right) / 2); if (arr[mid] === target) return mid; arr[mid] < target ? (left = mid + 1) : (right = mid - 1); } return -1; } ``` ### 旋转数组查找 ```js function searchRotated(nums, target) { let left = 0, right = nums.length - 1; while (left <= right) { const mid = Math.floor((left + right) / 2); if (nums[mid] === target) return mid; // 左半边有序 if (nums[left] <= nums[mid]) { if (target >= nums[left] && target < nums[mid]) right = mid - 1; else left = mid + 1; } else { // 右半边有序 if (target > nums[mid] && target <= nums[right]) left = mid + 1; else right = mid - 1; } } return -1; } ``` --- ## 7. 斐波那契数列 > **场景**:算法入门经典题、理解递归与动态规划思想、缓存优化演示、爬楼梯问题变种。 > **解决**:求第 n 位斐波那契数(F(0)=0, F(1)=1, F(n)=F(n-1)+F(n-2))。 ### 方法一:普通递归(不推荐) ```js // 时间复杂度 O(2^n),存在大量重复计算 function fib(n) { if (n <= 1) return n; return fib(n - 1) + fib(n - 2); } ``` ### 方法二:记忆化递归 ```js // 时间复杂度 O(n),空间复杂度 O(n) function fib(n, memo = {}) { if (n <= 1) return n; if (memo[n]) return memo[n]; return memo[n] = fib(n - 1, memo) + fib(n - 2, memo); } ``` ### 方法三:动态规划 ```js // 时间复杂度 O(n),空间复杂度 O(n) function fib(n) { if (n <= 1) return n; const dp = [0, 1]; for (let i = 2; i <= n; i++) { dp[i] = dp[i - 1] + dp[i - 2]; } return dp[n]; } ``` ### 方法四:空间优化(推荐) ```js // 时间复杂度 O(n),空间复杂度 O(1) function fib(n) { if (n <= 1) return n; let prev = 0, curr = 1; for (let i = 2; i <= n; i++) { [prev, curr] = [curr, prev + curr]; } return curr; } ``` ### 方法五:矩阵快速幂(大数优化) ```js // 时间复杂度 O(log n),适合求极大位数 function fib(n) { if (n <= 1) return n; const multiply = (a, b) => [ [a[0][0] * b[0][0] + a[0][1] * b[1][0], a[0][0] * b[0][1] + a[0][1] * b[1][1]], [a[1][0] * b[0][0] + a[1][1] * b[1][0], a[1][0] * b[0][1] + a[1][1] * b[1][1]] ]; const power = (m, p) => { let result = [[1, 0], [0, 1]]; // 单位矩阵 while (p > 0) { if (p & 1) result = multiply(result, m); m = multiply(m, m); p >>= 1; } return result; }; const matrix = [[1, 1], [1, 0]]; return power(matrix, n - 1)[0][0]; } ``` | 方法 | 时间复杂度 | 空间复杂度 | 适用场景 | |------|-----------|-----------|----------| | 普通递归 | O(2^n) | O(n) | 仅理解思想 | | 记忆化递归 | O(n) | O(n) | 面试常考 | | 动态规划 | O(n) | O(n) | 面试常考 | | 空间优化 | O(n) | O(1) | **推荐** | | 矩阵快速幂 | O(log n) | O(1) | 大数/竞赛 |