链表:
1.链表反转
let reverseList = function(head) {
//判断下变量边界问题
if(!head || !head.next)
return head;
//初始设置为空,因为第一个节点反转后就是尾部,尾部节点指向null
let pre = null,
current = head,
next;
// 判断当前节点是否为空,不为空就获取当前节点的下一个节点
// 然后把当前节点的next设为上一个节点,然后把current设为下一个节点,pre设为当前节点。
while(current) {
next = current.next;
current.next = pre;
pre = current;
current = next
}
return pre;
}
树:
1.二叉树的先序,中序,后序遍历(递归方式/非递归方式)
// 递归实现
function TreeNode(val) {
this.val = val;
this.left = this.right = null;
}
var traversal = function(root) {
if(root) {
//先序
console.log(root)
traversal(root.left)
// 中序
// console.log(root)
traversal(root.right)
// 后序
// console.log(root)
}
}
// 对于递归的实现来说,只需要理解每个节点都会被访问三次就明白为什么这样实现了。
// 非递归实现:使用了栈的结构,通过栈的先进后出模拟递归实现
//先序遍历
function pre(root) {
if(root) {
let stack = [];
stack.push(root)
while(stack.length > 0) {
root = stack.pop();
console.log(root);
if(root.right)
stack.push(root.right)
if(root.left)
stack.push(root.left)
}
}
}
// 中序遍历
function mid(root) {
if(root) {
let stack = [];
// 中序遍历是先左再根最后右
// 所以首先应该先把最左边节点遍历到底依次 push 进栈
// 当左边没有节点时,就打印栈顶元素,然后寻找右节点
// 对于最左边的叶节点来说,可以把它看成是两个 null 节点的父节点
// 左边打印不出东西就把父节点拿出来打印,然后再看右节点
while(stack.length > 0 || root) {
if(root){
stack.push(root)
root = root.left;
}else{
root = stack.pop();
console.log(root);
root = root.right;
}
}
}
}
// 后序遍历,使用两个栈来遍历
function pos(root) {
if(root){
let stack1 = [], stack2 = [];
stack1.push(root);
while(stack1.length > 0) {
root = stack1.pop();
stack2.push(root)
if(root.left) {
stack1.push(root.left);
}
if(root.right){
stack1.push(root.right)
}
}
while(stack2.lenght > 0) {
console.log(s2.pop())
}
}
}
2.中序遍历的前驱后继节点树的深度
// 中序遍历的前驱后继节点
// 前驱节点
function predecessor(node) {
if(!node)
return;
if(node.left) {
return getRight(node.left)
}
else {
let parent = node.parent;
while(parent && parent.right !== node) {
node = parent;
parent = node.parent
}
return parent;
}
}
function getRight(node) {
if(!node) {
return;
}
node = node.right;
while(node)
node = node.right
return node.parent;
}
// 后继节点
function successor(node) {
if(!node)
return
if(node.right) {
return getLeft(node.getRight)
}
else {
let parent = node.parent;
while(parent && parent.left !== node) {
node = parent;
parent = node.parent;
}
return parent;
}
}
function getLeft(node) {
if(!node){
return;
}
node = node.left;
while(node)
node = node.left;
return node.parent;
}
3.树的深度
// 树的深度
var maxDepth = function(root) {
if (!root) return 0
return Math.max(maxDepth(root.left), maxDepth(root.right)) + 1
}
4.二叉搜索树
// 二叉搜索树 BST
class Node {
constructor(value) {
this.value = value
this.left = null;
this.right = null
}
}
class BST {
constructor() {
this.root = null;
this.size = 0
}
getSize() {
return this.size;
}
isEmpty() {
return this.size === 0;
}
addNode(v) {
this.root = this._addChild(this.root, v)
}
_addChild(node, v) {
if(!node) {
this.size++;
return new Node(v)
}
if(node.value > v) {
node.left = this._addChild(node.left, v);
}
else if(node.value < v) {
node.right = this._addChild(node.right, v)
}
return node;
}
// 深度遍历
preTraversal() {
this._pre(this.root)
}
_pre(node) {
if (node) {
console.log(node.value)
this._pre(node.left)
this._pre(node.right)
}
}
// 中序遍历可用于排序
// 对于 BST 来说,中序遍历可以实现一次遍历就
// 得到有序的值
// 中序遍历表示先访问左节点,然后访问根节点,最后访问右节点。
midTraversal() {
this._mid(this.root)
}
_mid(node) {
if (node) {
this._mid(node.left)
console.log(node.value)
this._mid(node.right)
}
}
// 后序遍历可用于先操作子节点
// 再操作父节点的场景
// 后序遍历表示先访问左节点,然后访问右节点,最后访问根节点。
backTraversal() {
this._back(this.root)
}
_back(node) {
if (node) {
this._back(node.left)
this._back(node.right)
console.log(node.value)
}
}
// 广度遍历
breadthTraversal() {
if(this.root)
return null;
let q = new Queue();
q.enQueue(this.root)
while(!q.isEmpty()) {
let n = q.deQueue();
console.log(n.value);
if(n.left) q.enQueue(n.left)
if(n.right) q.enQueue(n.right)
}
}
//寻找最大值或最小值
getMin() {
return this._getMin(this.root).value;
}
_getMin(node) {
if(!node.left)
return node;
return this._getMin(node.left)
}
getMax() {
return this._getMax(this.root).value
}
_getMax(node) {
if(!node.right)
return node;
return this._getMax(node.right);
}
floor(v) {
let node = this._floor(this.root, v);
return node ? node.value : null
}
_floor(node, v) {
if(!node)
return null;
if(node.value === v)
return v;
if(node.value > v) {
return this._floor(node.left, v);
}
let right = this._floor(node.right, v)
if(right)
return right;
return node;
}
}
动态规划:
动态规划背后的基本思想非常简单,就是将一个问题拆分为子问题,一般来说这些子问题就是非常相似的,
那么我们可以通过只解决一次每个子问题来达到减少计算量的目的。一旦得出每个子问题的解,就存储该结果以便下次使用。
1.斐波那契数列
// 1. 存在很严重的性能问题,当n越大的时候,需要的时间是指数增加的
function fib(n) {
if(n < 2 && n >= 0){
return n;
}
return fib(n-1) + fib(n-2);
}
console.log(fib(10))
// 动态规划 1.1字底向上分解子问题 1.2 通过变量存储已经计算过的解
function fib(n) {
let array = new Array(n + 1).fill(null)
array[0] = 0
array[1] = 1
for (let i = 2; i <= n; i++) {
array[i] = array[i - 1] + array[i - 2];
}
return array[n]
}
console.log(fib(10))
2.0 - 1 背包问题
// 0 - 1 背包问题
/**
* @param {*} w 物品重量
* @param {*} v 物品价值
* @param {*} C 总容量
* @returns
*/
function knapsack(w, v, C) {
let length = w.length;
if(length === 0) return 0;
let array = new Array(length).fill(new Array(C + 1).fill(null));
for(let i = 0; i <= C; i++) {
array[0][i] = i >= w[0] ? v[0] : 0;
}
// 自底向上开始解决子问题,从物品2开始
for (let i = 1; i < length; i++) {
for(let j = 0; j <= C; j++) {
array[i][j] = array[i-1][j];
if(j >= w[i]) {
array[i][j] = Math.max(array[i][j], v[i] + array[i-1][j-1])
}
}
}
return array[length - 1][C];
}
let w = [1, 2, 3], v = [3, 7, 12], C = 5;
console.log('0 - 1背包问题', knapsack(w, v, C))
3.最长递增子序列
//最长递增子序列
function lis(n) {
if(n.length === 0)
return 0;
let array = new Array(n.length).fill(1);
for(let i = 1; i < n.length; i++) {
for(let j = 0; j < i; j++) {
if(n[i] > n[j]) {
array[i] = Math.max(array[i], 1 + array[j])
}
}
}
let res = 1;
for(let i = 0; i < array.length; i++) {
res = Math.max(res, array[i])
}
return res;
}
console.log('mzry', lis([0, 3, 4, 17, 2, 8, 6, 10]))
4.约瑟夫环
function ysfh(N, M) {
if (N < 1 || M < 1) {
return;
}
const source = Array(...Array(N)).map((_, i) => i + 1);
let index = 0;
while (source.length) {
index = (index + M - 1) % source.length;
console.log(source[index]);
source.splice(index, 1);
}
}
排序: 详见https://blog.csdn.net/mzrybbd/article/details/82941406