二叉树高频题(上)
二叉树高频题(上)
102. 二叉树的层序遍历
#include <vector>
#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode() : val(0), left(nullptr), right(nullptr) {}
TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
};
class Solution {
public:
vector<vector<int>> levelOrder(TreeNode *root) {
if (root == nullptr) return vector<vector<int>>();
vector<vector<int>> res;
queue<TreeNode *> q;
q.emplace(root);
while (!q.empty()) {
int len = q.size();
vector<int> curLever;
// 一层一层遍历
for (int i = 0; i < len; ++i) {
TreeNode *node = q.front();
q.pop();
curLever.emplace_back(node->val);
// 下层节点入队
if (node->left != nullptr) q.emplace(node->left);
if (node->right != nullptr) q.emplace(node->right);
}
res.emplace_back(curLever);
}
return res;
}
};
103. 二叉树的锯齿形层序遍历
#include <vector>
#include <iostream>
#include <algorithm>
#include <queue>
#include <stack>
using namespace std;
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode() : val(0), left(nullptr), right(nullptr) {}
TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
};
class Solution {
public:
vector<vector<int>> zigzagLevelOrder(TreeNode *root) {
if (root == nullptr) return vector<vector<int>>();
vector<vector<int>> res;
stack<int> stk;
queue<TreeNode *> q;
q.emplace(root);
bool flag = true;
while (!q.empty()) {
int len = q.size();
vector<int> curLever;
// 一层一层遍历
for (int i = 0; i < len; ++i) {
TreeNode *node = q.front();
q.pop();
if (flag == true) {
curLever.emplace_back(node->val);
} else {
stk.emplace(node->val);
}
// 下层节点入队
if (node->left != nullptr) q.emplace(node->left);
if (node->right != nullptr) q.emplace(node->right);
}
flag = !flag;
while (!stk.empty()) {
curLever.emplace_back(stk.top());
stk.pop();
}
res.emplace_back(curLever);
}
return res;
}
};
662. 二叉树最大宽度
- 层序遍历
#include <vector>
#include <iostream>
#include <algorithm>
#include <queue>
#include <stack>
using namespace std;
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode() : val(0), left(nullptr), right(nullptr) {}
TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
};
class Solution {
public:
int widthOfBinaryTree(TreeNode *root) {
if (root == nullptr) return 1;
int res = 1;
// 给节点加上编号,有溢出的可能
queue<pair<TreeNode *, unsigned long long>> q;
q.emplace(make_pair(root, 0));
while (!q.empty()) {
int len = q.size();
// 当前层最左和最右的节点编号
unsigned long long firstIndex;
unsigned long long lastIndex;
// 一层一层遍历
for (int i = 0; i < len; ++i) {
auto p = q.front();
q.pop();
TreeNode *node = p.first;
unsigned long long index = p.second;
if (i == 0) firstIndex = index;
if (i == len - 1) lastIndex = index;
// 下层节点入队
if (node->left != nullptr) q.emplace(make_pair(node->left, 2 * index + 1));
if (node->right != nullptr) q.emplace(make_pair(node->right, 2 * index + 2));
}
// 更新最大宽度
res = lastIndex - firstIndex + 1 > res ? lastIndex - firstIndex + 1 : res;
}
return res;
}
};
- DFS
#include <vector>
#include <iostream>
#include <algorithm>
#include <queue>
#include <stack>
#include <unordered_map>
using namespace std;
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode() : val(0), left(nullptr), right(nullptr) {}
TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
};
class Solution {
public:
unsigned long long result = 0;
// <level 层, level 层最左节点的编号>
unordered_map<int, unsigned long long> map;
int widthOfBinaryTree(TreeNode *root) {
dfs(root, 0, 0);
return result;
}
void dfs(TreeNode *node, unsigned long long nodeIndex, int level) {
if (node == nullptr) return;
if (map.count(level) == 0) map[level] = nodeIndex;
result = max(result, nodeIndex - map[level] + 1);
dfs(node->left, 2 * nodeIndex + 1, level + 1);
dfs(node->right, 2 * nodeIndex + 2, level + 1);
}
};
104. 二叉树的最大深度
- 层序遍历
#include <vector>
#include <algorithm>
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode() : val(0), left(nullptr), right(nullptr) {}
TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
};
class Solution {
public:
int maxDepth(TreeNode *root) {
if (root == nullptr) return 0;
int depth = 0;
const int size = 5002;
// 循环队列
struct TreeNode *queue[size];
int front = 0, rear = 0;
queue[rear++] = root;
while (front != rear) {
int count = (rear - front + size) % size;
// 一层加一次
depth++;
while (count-- > 0) {
struct TreeNode *node = queue[(front++) % size];
if (node->left != nullptr) queue[(rear++) % size] = node->left;
if (node->right != nullptr) queue[(rear++) % size] = node->right;
}
}
return depth;
}
};
- 递归
#include <vector>
#include <algorithm>
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode() : val(0), left(nullptr), right(nullptr) {}
TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
};
class Solution {
public:
int maxDepth(TreeNode *root) {
if (root == nullptr) return 0;
int left = maxDepth(root->left);
int right = maxDepth(root->right);
return (left > right ? left : right) + 1;
}
};
111. 二叉树的最小深度
- 层序遍历
#include <vector>
#include <algorithm>
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode() : val(0), left(nullptr), right(nullptr) {}
TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
};
class Solution {
public:
int minDepth(TreeNode *root) {
if (root == nullptr) return 0;
const int size = 50002;
struct TreeNode *queue[size];
int front = 0;
int rear = 0;
int depth = 0;
queue[rear++] = root;
while (front != rear) {
int count = (rear - front + size) % size;
depth++;
while (count-- > 0) {
struct TreeNode *node = queue[(front++) % size];
// 首次遇到没有孩子的时候,就是最小深度
if (node->left == nullptr && node->right == nullptr)
return depth;
if (node->left != nullptr)queue[(rear++) % size] = node->left;
if (node->right != nullptr) queue[(rear++) % size] = node->right;
}
}
return depth;
}
};
- DFS
#include <vector>
#include <algorithm>
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode() : val(0), left(nullptr), right(nullptr) {}
TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
};
class Solution {
public:
int minDp;
void dfs(TreeNode *node, int currentDepth) {
if (node == nullptr) return;
currentDepth++;
// 更新最小深度
if ((node->left == nullptr && node->right == nullptr)
&& currentDepth < minDp)
minDp = currentDepth;
dfs(node->left, currentDepth);
dfs(node->right, currentDepth);
}
int minDepth(TreeNode *root) {
if (root == nullptr) return 0;
minDp = INT_MAX;
dfs(root, 0);
return minDp;
}
};
- 递归
#include <vector>
#include <algorithm>
using namespace std;
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode() : val(0), left(nullptr), right(nullptr) {}
TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
};
class Solution {
public:
// 自底向上
int minDepth(TreeNode *root) {
if (root == nullptr) return 0;
if (root->left == nullptr && root->right == nullptr) return 1;
int lD = INT_MAX;
int rD = INT_MAX;
if (root->left != nullptr) lD = minDepth(root->left);
if (root->right != nullptr) rD = minDepth(root->right);
return min(lD, rD) + 1;
}
};
297. 二叉树的先序列化与反序列化
- 二叉树可以通过先序、后序或者按层遍历的方式序列化和反序列化
- 但是,二叉树无法通过中序遍历的方式实现序列化和反序列化
- 因为不同的两棵树,可能得到同样的中序序列,即便补了空位置也可能一样。
#include <vector>
#include <algorithm>
#include <string>
#include <regex>
#include <iostream>
using namespace std;
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};
class Codec {
public:
int cnt;
void encode(TreeNode *root, string &str) {
if (root == nullptr) {
str.append("#,");
return;
}
str.append(to_string(root->val) + ",");
encode(root->left, str);
encode(root->right, str);
}
TreeNode *decode(vector<string> &vals) {
string cur = vals[cnt++];
if (cur == "#") return nullptr;
TreeNode *node = new TreeNode(stoi(cur));
node->left = decode(vals);
node->right = decode(vals);
return node;
}
string serialize(TreeNode *root) {
string res = "";
encode(root, res);
return res;
}
TreeNode *deserialize(string data) {
vector<string> vals = split(data, ",");
cnt = 0;
return decode(vals);
}
vector<string> split(const string &str, const string &split) {
vector<string> res;
// 匹配 split
regex reg(split);
sregex_token_iterator pos(str.begin(), str.end(), reg, -1);
for (decltype(pos) end; pos != end; ++pos)
res.push_back(pos->str());
return res;
}
};
297. 二叉树的层序列化与反序列化
#include <vector>
#include <algorithm>
#include <string>
#include <regex>
#include <iostream>
#include <queue>
using namespace std;
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};
class Codec {
public:
// 层序遍历
void encode(TreeNode *root, string &str) {
queue<TreeNode *> q;
q.emplace(root);
while (!q.empty()) {
TreeNode *cur = q.front();
q.pop();
if (cur == nullptr) {
str.append("#,");
} else {
str.append(to_string(cur->val) + ",");
// 空指针也加入
q.emplace(cur->left);
q.emplace(cur->right);
}
}
}
TreeNode *generate(string val) {
return val == "#" ? nullptr : new TreeNode(stoi(val));
}
TreeNode *decode(vector<string> &vals) {
int cnt = 0;
TreeNode *root = generate(vals[cnt++]);
queue<TreeNode *> q;
q.emplace(root);
while (!q.empty()) {
TreeNode *node = q.front();
q.pop();
if (node == nullptr) continue;
node->left = generate(vals[cnt++]);
node->right = generate(vals[cnt++]);
if (node->left != nullptr) q.emplace(node->left);
if (node->right != nullptr) q.emplace(node->right);
}
return root;
}
string serialize(TreeNode *root) {
string res = "";
encode(root, res);
return res;
}
TreeNode *deserialize(string data) {
vector<string> vals = split(data, ",");
return decode(vals);
}
vector<string> split(const string &str, const string &split) {
vector<string> res;
// 匹配 split
regex reg(split);
sregex_token_iterator pos(str.begin(), str.end(), reg, -1);
for (decltype(pos) end; pos != end; ++pos)
res.push_back(pos->str());
return res;
}
};
105. 从前序与中序遍历序列构造二叉树
-
todo
-
利用先序与中序遍历序列构造二叉树
-
无重复值
#include <vector>
#include <algorithm>
#include <string>
#include <regex>
#include <iostream>
#include <stack>
using namespace std;
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode() : val(0), left(nullptr), right(nullptr) {}
TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
};
class Solution {
public:
TreeNode *buildTree(vector<int> &preorder, vector<int> &inorder) {
if (preorder.size() == 0) return nullptr;
int pre = 0;
int in = 0;
stack<TreeNode *> stk;
// 先序遍历的第一个值作为根节点
TreeNode *curRoot = new TreeNode(preorder[pre++]);
TreeNode *res = curRoot;
stk.emplace(curRoot);
for (; pre < preorder.size(); pre++) {
if (curRoot->val == inorder[in]) {
// 当前根节点刚好是中序序列的首个节点,说明当前根节点没有左子树
while (!stk.empty() && stk.top()->val == inorder[in]) {
curRoot = stk.top();
stk.pop();
in++;
}
TreeNode *node = new TreeNode(preorder[pre]);
curRoot->right = node;
curRoot = curRoot->right;
stk.emplace(curRoot);
} else {
// 当前根节点有左子树,且就是先序序列中当前根节点后面的一个节点
TreeNode *node = new TreeNode(preorder[pre]);
curRoot->left = node;
// 左子树根节点入栈
curRoot = curRoot->left;
stk.emplace(curRoot);
}
}
return res;
}
};
- 递归
#include <vector>
#include <algorithm>
using namespace std;
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode() : val(0), left(nullptr), right(nullptr) {}
TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
};
class Solution {
public:
int pre;
int in;
TreeNode *generate(vector<int> &preorder, vector<int> &inorder, int stop) {
if (pre == preorder.size()) return nullptr;
if (inorder[in] == stop) {
// 说明以 stop 为根节点的左子树已经生成完毕
in++;
return nullptr;
}
int rootVal = preorder[pre++];
TreeNode *root = new TreeNode(rootVal);
// 只有左子树生成完毕,才会遇到他的 stop,也就是左子树的父节点
root->left = generate(preorder, inorder, rootVal);
// root 子树是以 stop 为父节点的左子树
root->right = generate(preorder, inorder, stop);
return root;
}
TreeNode *buildTree(vector<int> &preorder, vector<int> &inorder) {
pre = 0;
in = 0;
return generate(preorder, inorder, INT_MAX);
}
};
- 递归
#include <vector>
#include <algorithm>
#include <string>
#include <regex>
#include <iostream>
#include <stack>
#include <unordered_map>
using namespace std;
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode() : val(0), left(nullptr), right(nullptr) {}
TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
};
class Solution {
public:
unordered_map<int, int> map;
TreeNode *generate(vector<int> &preorder, int rootIndex, int left, int right) {
if (left > right) return nullptr;
TreeNode *node = new TreeNode(preorder[rootIndex]);
// 当前根节点在中序序列中的位置
int in = map[preorder[rootIndex]];
// 左子树递归,左子树的根节点在先序序列中的位置为 rootIndex + 1
// 左子树的节点在中序序列的位置为 [left, in - 1]
node->left = generate(preorder, rootIndex + 1, left, in - 1);
// 右子树递归,右子树的根节点在先序序列中的位置为 rootIndex + in - left + 1
// 右子树的节点在中序序列的位置为 [in + 1, right]
node->right = generate(preorder, rootIndex + in - left + 1, in + 1, right);
return node;
}
TreeNode *buildTree(vector<int> &preorder, vector<int> &inorder) {
// 记录位置
for (int i = 0; i < inorder.size(); i++)
map[inorder[i]] = i;
return generate(preorder, 0, 0, inorder.size() - 1);
}
};
958. 二叉树的完全性检验
#include <vector>
#include <algorithm>
#include <string>
#include <regex>
#include <iostream>
#include <stack>
#include <queue>
using namespace std;
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode() : val(0), left(nullptr), right(nullptr) {}
TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
};
class Solution {
public:
bool isCompleteTree(TreeNode *root) {
if (root == nullptr) return true;
queue<TreeNode *> q;
q.emplace(root);
// 是否已经遇到第一个孩子不全的节点
bool leaf = false;
while (!q.empty()) {
TreeNode *node = q.front();
q.pop();
// 已经遇到第一个孩子不全的节点,如果后面遇到的不是叶子节点,说明不是完全二叉树
if (leaf == true
&& (node->left != nullptr || node->right != nullptr))
return false;
// 只有右孩子肯定不是完全二叉树
if (node->left == nullptr && node->right != nullptr) return false;
// 入队
if (node->left != nullptr) q.emplace(node->left);
if (node->right != nullptr) q.emplace(node->right);
// 标记已经遇到
if (node->left == nullptr || node->right == nullptr) leaf = true;
}
return true;
}
};
222. 完全二叉树的节点个数
#include <vector>
#include <algorithm>
#include <string>
#include <regex>
#include <iostream>
#include <stack>
#include <queue>
#include <valarray>
using namespace std;
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode() : val(0), left(nullptr), right(nullptr) {}
TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
};
class Solution {
public:
// 完全二叉树的深度
int getDepth(TreeNode *root) {
int depth = 0;
while (root != nullptr) {
depth++;
root = root->left;
}
return depth;
}
// 时间复杂度 O(logn ^ 2)
int countNodes(TreeNode *root) {
if (root == nullptr) return 0;
int leftDepth = getDepth(root->left);
int rightDepth = getDepth(root->right);
int leftCnt = 0;
int rightCnt = 0;
if (leftDepth == rightDepth) {
// 左子树必满
leftCnt = pow(2, leftDepth) - 1;
// 递归计算右子树
rightCnt = countNodes(root->right);
} else {
// 右子树必满
rightCnt = pow(2, rightDepth) - 1;
// 递归计算左子树
leftCnt = countNodes(root->left);
}
return leftCnt + rightCnt + 1;
}
};