269 lines
4.9 KiB
Markdown
269 lines
4.9 KiB
Markdown
# 数据结构与算法
|
|
|
|
## 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. 二叉树
|
|
|
|
### 遍历(前中后序)
|
|
|
|
```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. 栈与队列
|
|
|
|
### 用栈实现队列
|
|
|
|
```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. 哈希表
|
|
|
|
### 两数之和
|
|
|
|
```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. 二分查找
|
|
|
|
### 基础二分查找
|
|
|
|
```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;
|
|
}
|
|
```
|