总结题目ing~
续上周~~
标题没有错,是按照本地文件夹目录结构划分的
使用栈实现
非递归实现
递归实现
function reverseList(head) {
if (head === null) return null;
if (head.next === null) return head;
const stack = [];
let current = head;
while (current) {
stack.push(current);
current = current.next;
}
const newHead = stack.pop();
let currentNode = newHead;
while (stack.length) {
const node = stack.pop();
currentNode.next = node;
currentNode = currentNode.next;
}
currentNode.next = null;
return newHead;
}
function reverseList(head) {
if (head === null || head.next === null) return head
let newHead = null
while (head) {
let current = head.next
head.next = newHead
newHead = head
head = current
}
return newHead
}
function reverseList(head) {
if (head === null || head.next === null) return head;
const newHead = reverseList(head.next);
head.next.next = head;
head.next = null;
return newHead;
}
输入:l1 = [2,4,3], l2 = [5,6,4]
输出:[7,0,8]
function addTwoNumbers(l1, l2) {
const l3 = new ListNode(0);
let p1 = l1;
let p2 = l2;
let carry = 0;
while (p1 || p2) {
const v1 = p1.val;
const v2 = p2.val;
const val = v1 + v2 + carry;
carry = Math.floor(val / 10);
l3.next = new ListNode(val % 10);
if (p1) p1 = p1.next;
if (p2) p2 = p2.next;
}
if (carry) l3.next = new ListNode(carry);
return l3.next;
}
输入:head = [1,1,2]
输出:[1,2]
function deleteRepeatVal(head) {
let p = head;
while (p && p.next) {
if (p.next.val === p.val) {
p.next = p.next.next;
} else {
p = p.next;
}
}
return head;
}
输入:head = [1,2,3,3,4,4,5]
输出:[1,2,5]
function deleteRepeatVal(head) {
if (!head) {
return head;
}
const dummy = new ListNode(0, head);
let cur = dummy;
while (cur.next && cur.next.next) {
if (cur.next.val === cur.next.next.val) {
const x = cur.next.val;
while (cur.next && cur.next.val === x) {
cur.next = cur.next.next;
}
} else {
cur = cur.next;
}
}
return dummy.next;
}
基于数组实现的,但是相对于数组,它有很多的优势
可以提供非常快速的插入-删除-查找操作O(1)
速度比树还要快
编码比树容易
不足:
数据没有顺序,不能以固定的方式遍历其中的元素
通常情况下,key 是不允许重复的,不能放置相同的 key
到底是什么
结构就是数组,神奇的地方在于对数组下标值的一种变换
变换:使用哈希函数获取到 HashCode
好的哈希函数
function hashFn(key, max) {
let hashCode = 0;
for (let i = 0; i < key.length; i++) {
hashCode += key.charCodeAt(i) + hashCode * 31;
}
const index = hashCode % max;
return index;
}
使用类进行构建
属性
方法
增、改
put
删
查
class HashTable {
storage;
length = 7;
count = 0;
// 哈希函数
hashFn(key, max) {
let hashCode = 0;
for (let i = 0; i < key.length; i++) {
hashCode += key.charCodeAt(i) + hashCode * 31;
}
const index = hashCode % max;
return index;
}
// 增、改
put(key, value) {
const index = this.hashFn(key, this, length);
let bucket = this.storage[index];
if (!bucket) {
bucket = [];
this.storage[index] = bucket;
}
let isUpdate = false;
for (let i = 0; i < bucket.length; i++) {
const tuple = bucket[i];
if (key === tuple[0]) {
tuple[1] = value;
isUpdate = true;
}
}
if (!isUpdate) {
bucket.push([key, value]);
this.count++;
}
}
// 查
get(key) {
const index = this.hashFn(key, this.length);
const bucket = this.storage[index];
if (!bucket) {
return undefined;
}
for (let i = 0; i < bucket.length; i++) {
const tuple = bucket[i];
if (tuple[0] === key) {
return tuple[1];
}
}
return undefined;
}
// 删
delete(key) {
const index = this.hashFn(key, this.length)
const bucket = this.storage[index]
if (!bucket) return undefined
for (let i = 0; i < bucket.length; i++){
const tuple = bucket[i]
if (tuple[0] === key) {
bucket.splice(i, 1)
this.count--
return tuple[1]
}
}
}
}
数据量增大会造成 bucket 越来越长,造成效率的降低
初始化数组长度
存储之前的 oldStorage,之后对哈希表进行初始化
遍历之前的每一个桶
没有桶直接返回
遍历每一个桶中的元素
调用 put 方法将其放入到新的数组中
isPrime(num) {
const sqrt = Math.sqrt(num);
for (let i = 0; i <= sqrt; i++) {
if (sqrt % i === 0) return false;
}
return true
}
resize(newLength) {
let newPrimeLength = newLength
while (!this.isPrime(newLength)) {
newPrimeLength++
}
this.length = newPrimeLength
const oldStorage = this.storage
this.storage = []
this.count = 0
oldStorage.forEach(bucket => {
if(!bucket) return
for (let i = 0; i < bucket.length; i++){
const tuple = bucket[i]
this.put([tuple[0],tuple[1]])
}
})
}
class HashTable {
storage;
length = 7;
count = 0;
// 哈希函数
hashFn(key, max) {
let hashCode = 0;
for (let i = 0; i < key.length; i++) {
hashCode += key.charCodeAt(i) + hashCode * 31;
}
const index = hashCode % max;
return index;
}
// 增、改
put(key, value) {
const index = this.hashFn(key, this, length);
let bucket = this.storage[index];
if (!bucket) {
bucket = [];
this.storage[index] = bucket;
}
let isUpdate = false;
for (let i = 0; i < bucket.length; i++) {
const tuple = bucket[i];
if (key === tuple[0]) {
tuple[1] = value;
isUpdate = true;
}
}
if (!isUpdate) {
bucket.push([key, value]);
this.count++;
const loadFactor = this.count / this.length;
if (loadFactor > 0.75) {
this.resize(this.length * 2);
}
}
}
// 查
get(key) {
const index = this.hashFn(key, this.length);
const bucket = this.storage[index];
if (!bucket) {
return undefined;
}
for (let i = 0; i < bucket.length; i++) {
const tuple = bucket[i];
if (tuple[0] === key) {
return tuple[1];
}
}
return undefined;
}
// 删
delete(key) {
const index = this.hashFn(key, this.length);
const bucket = this.storage[index];
if (!bucket) return undefined;
for (let i = 0; i < bucket.length; i++) {
const tuple = bucket[i];
if (tuple[0] === key) {
bucket.splice(i, 1);
this.count--;
const loadFactor = this.count / this.length;
if (loadFactor < 0.25 && this.length > 7) {
this.resize(Math.floor(this.length / 2));
}
return tuple[1];
}
}
}
isPrime(num) {
const sqrt = Math.sqrt(num);
for (let i = 0; i <= sqrt; i++) {
if (sqrt % i === 0) return false;
}
return true;
}
resize(newLength) {
let newPrimeLength = newLength;
while (!this.isPrime(newLength)) {
newPrimeLength++;
}
this.length = newPrimeLength;
const oldStorage = this.storage;
this.storage = [];
this.count = 0;
oldStorage.forEach((bucket) => {
if (!bucket) return;
for (let i = 0; i < bucket.length; i++) {
const tuple = bucket[i];
this.put([tuple[0], tuple[1]]);
}
});
}
}
class TreeNode {
value;
left = null;
right = null;
constructor(value) {
this.value = value;
}
}
class BSTree {
root = null;
parent = null;
get isLeft() {
return !!(this.parent && this.parent.left === this);
}
get isRight() {
return !!(this.parent && this.parent.right === this);
}
insert(value) {
const newNode = new TreeNode(value);
if (!this.root) {
this.root = newNode;
} else {
this.insertNode(this.root, newNode);
}
}
insertNode(root, newNode) {
if (newNode.value <= root.value) {
if (root.left === null) {
root.left = newNode;
} else {
this.insertNode(root.left, newNode);
}
} else {
if (root.right === null) {
root.right = newNode;
} else {
this.insertNode(root.right, newNode);
}
}
}
// 遍历
preOrderTraverse() {
this.preOrderTraverseNode(root);
}
preOrderTraverseNode(node) {
if (node) {
console.log(node.value);
this.preOrderTraverseNode(node.left);
this.preOrderTraverseNode(node.right);
}
}
inOrderTraverse() {
this.inOrderTraverseNode(root);
}
inOrderTraverseNode(node) {
if (node) {
this.inOrderTraverseNode(node.left);
console.log(node.value);
this.inOrderTraverseNode(node.right);
}
}
postOrderTraverse() {
this.postOrderTraverseNode(root);
}
postOrderTraverseNode(node) {
if (node) {
this.postOrderTraverseNode(node.left);
this.postOrderTraverseNode(node.right);
console.log(node.value);
}
}
levelOrderTraverse() {
if (!this.root) return;
const queue = [];
queue.push(this.root);
while (queue.length) {
const node = queue.shift();
if (node.left) queue.push(node.left);
if (node.right) queue.push(node.right);
}
}
getMaxValue() {
let current = this.root;
while (current && current.right) {
current = current.right;
}
return current.value;
}
getMinValue() {
let current = this.root;
while (current && current.left) {
current = current.left;
}
return current.value;
}
search(value) {
let current = this.root;
if (current.value === value) {
return true;
} else if (current.value > value) {
current = current.left;
} else {
current = current.right;
}
return false;
}
searchNode(value) {
let current = this.root;
let parent = null;
while (current) {
if (current.value === value) return current;
parent = current;
if (current.value < value) current = current.right;
if (current.value > value) current = current.left;
if (current) current.parent = current;
}
return null;
}
remove(value) {
const current = this.searchNode(value);
if (!current) return false;
let replaceNode = null;
if (current.left === null && current.right === null) {
replaceNode = null;
} else if (current.right === null) {
replaceNode = current.left;
} else if (current.left === null) {
replaceNode = current.right;
} else {
const successor = this.getSuccessor(current);
replaceNode = successor;
}
if (current === this.root) {
this.root = replaceNode;
} else if (current.isLeft) {
current.parent.left = replaceNode;
} else {
current.parent.right = replaceNode;
}
return true;
}
getSuccessor(delNode) {
let current = delNode.right;
let successor = null;
while (current) {
successor = current;
current = current.left;
if (current) current.parent = successor;
}
if (successor !== delNode.right) {
successor.parent.left = successor.right;
successor.right = delNode.right;
}
successor.left = delNode.left;
return successor;
}
}
class Graph {
verteces = [];
adjList = new Map();
addVertex(vertex) {
this.verteces.push(vertex)
this.adjList.set(vertex,[])
}
addEdge(v1, v2) {
this.adjList.get(v1).push(v2)
this.adjList.get(v2).push(v1)
}
}
dfs() {
if (this.verteces.length === 0) return;
const stack = [];
stack.push(this.verteces[0]);
const visited = new Set();
visited.add(this.verteces[0]);
while (stack.length) {
const vertex = stack.pop();
console.log(vertex);
const neighbors = this.adjList.get(vertex);
if (!neighbors) continue;
for (let i = neighbors.length - 1; i >= 0; i--) {
stack.push(neighbors[i]);
visited.add(neighbors[i]);
}
}
}
class Graph {
verteces = [];
adjList = new Map();
addVertex(vertex) {
this.verteces.push(vertex);
this.adjList.set(vertex, []);
}
addEdge(v1, v2) {
this.adjList.get(v1).push(v2);
this.adjList.get(v2).push(v1);
}
bfs() {
if (this.verteces.length === 0) return;
const queue = [];
queue.push(this.verteces[0]);
const visited = new Set();
visited.add(this.verteces[0]);
while (queue.length) {
const vertex = queue.shift();
console.log(vertex);
const neighbors = this.adjList.get(vertex);
if (!neighbors) continue;
for (let i = 0; i < neighbors.length; i++) {
if (!visited.has(neighbors[i])) {
queue.push(neighbors[i]);
visited.add(neighbors[i]);
}
}
}
}
}
判断矩阵是否存在
获取矩阵的行数和列数
构建两个矩阵,初始化为 false
遍历周围四个方向的坐标
遍历过标记为 true
满足限制条件
深度遍历
上左逆流而上,下右逆流而上
收集能流到两个大洋的坐标
function oean(height) {
if (!height[0] || !height) return [];
const m = height.length;
const n = height[0].length;
const flow1 = Array.from({ length: m }, () => new Array(n).fill(false));
const flow2 = Array.from({ length: m }, () => new Array(n).fill(false));
const dfs = (r, c, flow) => {
flow[r][c] = true[([r, c + 1], [r, c - 1], [r - 1, c], [r + 1, c])].forEach(([nr, nc]) => {
if (nr >= 0 && nc >= 0 && nr < m && nc < n && !flow[nr][nc] && height[nr][nc] >= flow[r][c]) {
dfs(nr, nc, flow);
}
});
};
for (let r = 0; r < m; r++) {
dfs(r, 0, flow1);
dfs(r, m - 1, flow2);
}
for (let c = 0; c < n; c++) {
dfs(0, c, flow1);
dfs(n - 1, c, flow2);
}
const res = [];
for (let i = 0; i < m; i++) {
for (let j = 0; j < n; j++) {
if (flow1[i][j] && flow2[i][j]) {
res.push([i, j]);
}
}
}
return res;
}
function cloneGraph1(node) {
if (!node) return;
const visited = new Map();
const dfs = (n) => {
const nCopy = new Node(n.val);
visited.set(n, nCopy);
(n.neighbors || []).forEach((neighbor) => {
if (!visited.has(neighbor)) {
dfs(neighbor);
}
nCopy.neighbors.push(visited.get(neighbor));
});
};
dfs(node);
return visited.get(node);
}
function cloneGraph2(node) {
if (!node) return;
const visited = new Map();
visited.set(node, new Node(node.val));
const queue = [node];
while (queue.length) {
const n = queue.shift();
(n.neighbors || []).forEach((neighbor) => {
if (!visited.has(neighbor)) {
queue.push(neighbor);
visited.set(neighbor, new Node(neighbor.val));
}
visited.get(n).neighbors.push(visited.get(neighbor));
});
}
return visited.get(node);
}
class Heap {
data = [];
length = 0;
swap(i, j) {
const temp = this.data[i];
this.data[i] = this.data[j];
this.data[j] = temp;
}
insert(value) {
this.data.push(value);
this.length++;
this.heapify_up();
}
heapify_up() {
const index = this.data.length - 1;
while (index > 0) {
let parentIndex = Math.floor((index - 1) / 2);
if (this.data[parentIndex] >= this.data[index]) {
break;
}
this.swap(index, parentIndex);
index = parentIndex;
}
}
extract() {
if (this.length === 0) return undefined;
if (this.length === 1) return this.data.pop();
const topValue = this.data[0];
this.data[0] = this.data.pop()
this.length--;
this.heapify_down(0);
return topValue;
}
heapify_down(index) {
while (2 * index + 1 < this.length) {
let leftindex = 2 * index + 1;
let rightIndex = 2 * index + 2;
let largerIndex = leftindex;
if (rightIndex <= this.length && this.data[leftindex] < this.data[rightIndex]) {
largerIndex = rightIndex;
}
if (this.data[index] >= this.data[largerIndex]) break;
this.swap(largerIndex, index);
index = largerIndex;
}
}
buildHeap(arr) {
this.data = arr;
this.length = arr.length;
const start = Math.floor((this.length - 1) / 2);
for (let i = start; start >= 0; start--) {
this.heapify_down(i);
}
}
peek() {
return this.data[0];
}
size() {
return this.length;
}
isEmpty() {
return this.length === 0;
}
}
function search(numbers, num) {
for (let i = 0; i < numbers.length; i++){
const item = numbers[i]
if(item === num) return i
}
return -1
}
function bsSearch(numbers, num) {
let left = 0;
let right = numbers.length - 1;
while (left <= right) {
let mid = Math.floor((left + right) / 2);
if (numbers[mid] === num) {
return mid;
} else if (numbers[mid] > num) {
right = mid - 1;
} else {
left = mid + 1;
}
}
return -1;
}