LeetCode 算法学习记录

2021/12/29

# 入门级算法

题目在 LeetCode 上,主要记个思路以及通用的解法

# 144.二叉树前序遍历

# 94.二叉树中序遍历

# 145.二叉树后序遍历

  • 只要理解了前中后序遍历的顺序,用 DFS 一把梭。前序:根->左->右;中序:左->根->右;后序:左->右->根;
  1. 递归:
const parse = (root) => {
	if (!root) return [];
	const res = [];
	const dfs = (node) => {
		res.push(node.val); // 调整这个顺序即可
		dfs(node.left);
		dfs(node.right);
	};
	dfs(root);
	return res;
};
1
2
3
4
5
6
7
8
9
10
11
  • 借助一个栈来进行节点的存储
  1. 迭代:
const parse = (root) => {
	if (!root) return [];
	const res = [];
	const stack = [];
	while (root || stack.length) {
		// 前
		while (root) {
			stack.push(root);
			res.push(root.val); // 前序是一访问到节点就记录
			root = root.left;
		}
		root = stack.pop();
		root = root.right;
		// 中
		while (root) {
			stack.push(root);
			root = root.left;
		}
		root = stack.pop();
		res.push(root.val); // 中序是等遍历到左侧最后一个节点时再开始记录
		root = root.right;
		// 后
		while (root) {
			stack.push(root);
			res.unshift(root.val); // 后序是一访问到节点就反向记录
			root = root.right;
		}
		root = stack.pop();
		root = root.left;
	}
	return res;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
  1. 颜色标记
const parse = (root) => {
	if (!root) return [];
	const [WHITE, DARK] = [0, 1];
	let color, node;
	const res = [];
	const stack = [[WHITE, root]];
	while (stack.length) {
		[color, node] = stack.pop();
		if (!node) continue;
		// 当前指向的结点是未访问过的结点,将其右节点,根节点,左节点依次入栈(后入先出)
		// 前
		if (color === WHITE) {
			stack.push([WHITE, node.right]);
			stack.push([WHITE, node.left]);
			stack.push([DARK, node]);
		} else {
			res.push(node.val);
		}
		// 中
		if (color === WHITE) {
			stack.push([WHITE, node.right]);
			stack.push([DARK, node]);
			stack.push([WHITE, node.left]);
		} else {
			res.push(node.val);
		}
		// 后
		if (color === WHITE) {
			stack.push([DARK, node]);
			stack.push([WHITE, node.right]);
			stack.push([WHITE, node.left]);
		} else {
			res.push(node.val);
		}
	}
	return res;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
  1. Morris 算法
// 中序
var inorderTraversal = function (root) {
	if (!root) return [];
	const res = [];
	let predecessor = null;
	while (root) {
		if (root.left) {
			predecessor = root.left;
			while (predecessor.right && predecessor.right !== root) {
				predecessor = predecessor.right;
			}
			if (!predecessor.right) {
				predecessor.right = root;
				root = root.left;
			} else {
				res.push(root.val);
				predecessor.right = null;
				root = root.right;
			}
		} else {
			res.push(root.val);
			root = root.right;
		}
	}
	return res;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

# 102.二叉树层序遍历

var levelOrder = function (root) {
	if (!root) return [];
	const res = [];
	const queue = [root];

	while (queue.length) {
		const levelSize = queue.length; // 表示当前这一层的节点数
		res.push([]); // 先把当前层的数组写入,然后利用res.length-1往里写数据
		for (let i = 0; i < levelSize; i++) {
			// 把当前层的所有节点都遍历一遍
			const node = queue.shift();
			res[res.length - 1].push(node.val);
			if (node.left) queue.push(node.left);
			if (node.right) queue.push(node.right);
		}
	}
	return res;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# 困难

# 297.二叉树的序列化与反序列化

  • 字节
  1. 思路:DFS,序列化时深度遍历每个节点,如果是空就加 null,如果不是空就加 node.toString(),反序列化时先 split,然后 DFS,从左到右依次处理成 TreeNode,处理完了的节点需要 shift 移除。
// Definition for a binary tree node.
function TreeNode(val) {
	this.val = val;
	this.left = this.right = null;
}

// 序列化:Tree => String
const serialize = function (root) {
	return rserialize(root, "");
};

const rserialize = (root, str) => {
	if (root === null) {
		str += "null,";
	} else {
		str += root.val + "" + ",";
		str = rserialize(root.left, str);
		str = rserialize(root.right, str);
	}
	return str;
};

// 反序列化:String => Tree
const deserialize = function (data) {
	const dataArray = data.split(",");
	return rdeserialize(dataArray);
};

const rdeserialize = (dataList) => {
	if (dataList[0] === "null") {
		dataList.shift();
		return null;
	}
	const root = new TreeNode(parseInt(dataList[0]));
	dataList.shift();
	root.left = rdeserialize(dataList);
	root.right = rdeserialize(dataList);
	return root;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
上次更新: 2/28/2022