目录
// 树的结构
struct TreeNode{
int val;
TreeNode *left, *right;
};
树的遍历方法
先序遍历
// 递归
void dfs(TreeNode *p) {
if (!p) return;
// 处理当前p节点
dfs(p->left);
dfs(p->right);
}
// 迭代
TreeNode *root;
stack<TreeNode*> S;
while (S.size() || root) {
while (root) {
S.push(root);
// 处理当前节点root
root = root->left;
}
root = S.top();
S.pop();
root = root->right;
}
中序遍历
// 递归
void dfs(TreeNode *p) {
if (!p) return;
dfs(p->left);
// 处理当前p节点
dfs(p->right);
}
// 迭代
TreeNode *root;
stack<TreeNode*> S;
while (S.size() || root) {
while (root) {
S.push(root);
root = root->left;
}
root = S.top();
S.pop();
// 处理当前节点root
root = root->right;
}
后序遍历
// 递归
void dfs(TreeNode *p) {
if (!p) return;
dfs(p->left);
dfs(p->right);
// 处理当前p节点
}
// 迭代
if (!root) return;
stack<TreeNode*> S1, S2;
S1.push(root);
while (S1.size()) {
TreeNode *tmp = S1.top();
S1.pop();
S2.push(tmp);
if (tmp->left)
S1.push(tmp->left);
if (tmp->right)
S1.push(tmp->right);
}
while (!S2.size()) {
TreeNode* tmp = S2.top();
S2.pop();
// 处理当前节点tmp
}
return res;
层次遍历
vector<vector<int>> levelOrder(TreeNode* root) {
queue<TreeNode*> Q;
vector<vector<int>> ret;
if (!root) return ret;
vector<int> res;
Q.push(root);
while (!Q.empty()) {
int siz = Q.size();
res.clear();
while (siz--) {
TreeNode *tmp = Q.front();
Q.pop();
res.push_back(tmp->val);
if (tmp->left) Q.push(tmp->left);
if (tmp->right) Q.push(tmp->right);
}
ret.push_back(res);
}
return ret;
}
二叉搜索树
二叉搜索树的LCA
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
TreeNode* ancestor = root;
while (1) {
if (p->val < ancestor->val && q->val < ancestor->val)
ancestor = ancestor->left;
else if (p->val > ancestor->val && q->val > ancestor->val)
ancestor = ancestor->right;
else break;
}
return ancestor;
}
二叉搜索树全排列
给1~n个节点,求这n个节点生成的二叉搜索树种类
// O(n^2)
int numTrees(int n) {
vector<vector<int>> dp(n+1, vector<int>(n+1));
for (int i = 1; i <= n; ++i)
dp[i][i] = 1;
for (int len = 1; len < n; ++len) {
for (int i = 1; i <= n-len; ++i) {
dp[i][i+len] += dp[i][i+len-1] + dp[i+1][i+len];
for (int j = i+1; j <= i+len-1; ++j) {
dp[i][i+len] += dp[i][j-1] * dp[j+1][i+len];
}
}
}
return dp[1][n];
}
// O(n^2)
int numTrees(int n) {
vector<int> dp(n+1, 1);
for (int i = 2; i <= n; ++i) {
dp[i] = 0;
for (int j = 1; j <= i; ++j) {
dp[i] += dp[j-1] * dp[i-j];
}
}
return dp[n];
}
// O(n)数学
int numTrees(int n) {
long long C = 1;
for (int i = 0; i < n; ++i)
C = C * 2 * (2 * i + 1) / (i + 2);
return C;
}
// 输出所有的树
vector<TreeNode*> gettree(int left, int right) {
if (left > right) return { nullptr };
vector<TreeNode*> ret;
for (int i = left; i <= right; ++i) {
vector<TreeNode*> lson = gettree(left, i-1);
vector<TreeNode*> rson = gettree(i+1, right);
for (int x = 0; x < lson.size(); ++x) {
for (int y = 0; y < rson.size(); ++y) {
TreeNode *mid = new TreeNode(i);
mid->left = lson[x];
mid->right = rson[y];
ret.push_back(mid);
}
}
}
return ret;
}
// 题意同上,返回所有二叉搜索树
vector<TreeNode*> generateTrees(int n) {
return gettree(1, n);
}
恢复二叉搜索树
// 空间复杂度为O(n)的做法
void dfs(TreeNode *p, vector<TreeNode*> &res) {
if (!p) return;
dfs(p->left, res);
res.push_back(p);
dfs(p->right, res);
}
void recoverTree(TreeNode* root) {
vector<TreeNode*> res;
dfs(root, res);
if (res.size() == 1) return;
int id1 = -1, id2 = -1;
for (int i = 0; i < res.size(); ++i) {
if (!i) {
if (res[i]->val >= res[i+1]->val) id1 = i;
}
else if (i == res.size()-1) {
if (res[i]->val <= res[i-1]->val) id2 = i;
}
else {
if (res[i]->val <= res[i-1]->val && res[i]->val <= res[i+1]->val
|| res[i]->val >= res[i-1]->val && res[i]->val >= res[i+1]->val) {
if (id1 == -1) id1 = i;
else id2 = i;
}
}
}
swap(res[id1]->val, res[id2]->val);
}
// Morris中序遍历,空间复杂度为O(1)
void recoverTree(TreeNode* root) {
TreeNode *x = nullptr, *y = nullptr, *pred = nullptr, *predecessor = nullptr;
while (root) {
if (root->left) {
// predecessor 节点就是当前 root 节点向左走一步,然后一直向右走至无法走为止
predecessor = root->left;
while (predecessor->right != nullptr && predecessor->right != root) {
predecessor = predecessor->right;
}
// 让 predecessor 的右指针指向 root,继续遍历左子树
if (!predecessor->right) {
predecessor->right = root;
root = root->left;
}
// 说明左子树已经访问完了,我们需要断开链接
else {
if (pred && root->val < pred->val) {
y = root;
if (!x) x = pred;
}
pred = root;
predecessor->right = nullptr;
root = root->right;
}
}
// 如果没有左孩子,则直接访问右孩子
else {
if (pred && root->val < pred->val) {
y = root;
if (!x) x = pred;
}
pred = root;
root = root->right;
}
}
swap(x->val, y->val);
}
有序数组转二叉搜索树
TreeNode* dfs(vector<int> &a, int l, int r) {
if (l > r)
return nullptr;
int m = (l+r)>>1;
TreeNode *ret = new TreeNode(a[m]);
ret->left = dfs(a, l, m-1);
ret->right = dfs(a, m+1, r);
return ret;
}
TreeNode* sortedArrayToBST(vector<int>& nums) {
TreeNode *ret = new TreeNode();
ret = dfs(nums, 0, nums.size()-1);
return ret;
}
有序链表转二叉搜索树
// 每次都要跑一次快慢指针获取中值,时间复杂度O(nlogn),空间复杂度O(nlogn)
ListNode* getMedian(ListNode* left, ListNode* right) {
ListNode* fast = left;
ListNode* slow = left;
while (fast != right && fast->next != right) {
fast = fast->next;
fast = fast->next;
slow = slow->next;
}
return slow;
}
TreeNode* buildTree(ListNode* left, ListNode* right) {
if (left == right) {
return nullptr;
}
ListNode* mid = getMedian(left, right);
TreeNode* root = new TreeNode(mid->val);
root->left = buildTree(left, mid);
root->right = buildTree(mid->next, right);
return root;
}
TreeNode* sortedListToBST(ListNode* head) {
return buildTree(head, nullptr);
}
// 中序遍历优化,时间复杂度O(n),空间复杂度O(logn)
int getLength(ListNode* head) {
int ret = 0;
for (; head != nullptr; ++ret, head = head->next);
return ret;
}
TreeNode* buildTree(ListNode*& head, int left, int right) {
if (left > right) {
return nullptr;
}
int mid = (left + right + 1) / 2;
TreeNode* root = new TreeNode();
root->left = buildTree(head, left, mid - 1);
root->val = head->val;
head = head->next;
root->right = buildTree(head, mid + 1, right);
return root;
}
TreeNode* sortedListToBST(ListNode* head) {
int length = getLength(head);
return buildTree(head, 0, length - 1);
}
二叉搜索树中第k小的节点
int kthSmallest(TreeNode* root, int k) {
stack<TreeNode*> S;
while (S.size() || root) {
while (root) {
S.push(root);
root = root->left;
}
root = S.top();
S.pop();
if (--k == 0) break;
root = root->right;
}
return root->val;
}
判断二叉树
验证二叉搜索树
bool is(TreeNode *p, long long minn, long long maxn) {
if (!p) return 1;
if (p->val <= minn || p->val >= maxn) return 0;
return (is(p->left, minn, p->val) && is(p->right, p->val, maxn));
}
// 判断该二叉树是否为二叉搜索树
bool isValidBST(TreeNode* root) {
return is(root, LONG_MIN, LONG_MAX);
}
判断对称二叉树
// 递归
bool is(TreeNode *a, TreeNode *b) {
if (!a && !b) return 1;
if (!a || !b) return 0;
return (a->val == b->val && is(a->left, b->right) && is(a->right, b->left));
}
// 给定一棵二叉树,判断是否为镜像树
bool isSymmetric(TreeNode* root) {
if (!root) return root;
return is(root->left, root->right);
}
// 迭代
bool check(TreeNode *u, TreeNode *v) {
queue <TreeNode*> q;
q.push(u); q.push(v);
while (!q.empty()) {
u = q.front(); q.pop();
v = q.front(); q.pop();
if (!u && !v) continue;
if ((!u || !v) || (u->val != v->val))
return false;
q.push(u->left);
q.push(v->right);
q.push(u->right);
q.push(v->left);
}
return true;
}
bool isSymmetric(TreeNode* root) {
return check(root, root);
}
判断平衡二叉树
// O(n^2)
int gdep(TreeNode *p) {
if (!p) return 0;
return max(gdep(p->left), gdep(p->right)) + 1;
}
bool isBalanced(TreeNode* root) {
if (!root) return true;
return (abs(gdep(root->left)-gdep(root->right)) <= 1) && isBalanced(root->left) && isBalanced(root->right);
}
// O(n)
int get_dep(TreeNode* root) {
if (!root) return 0;
int l_dep = get_dep(root->left);
int r_dep = get_dep(root->right);
if (l_dep < 0 || r_dep < 0 || abs(l_dep - r_dep) > 1)
return -1;
return max(l_dep, r_dep) + 1;
}
bool isBalanced(TreeNode* root) {
return get_dep(root) >= 0;
}
判断两棵树是否相同
bool isSameTree(TreeNode* p, TreeNode* q) {
if (!p && !q) return 1;
if (!p || !q) return 0;
return (p->val==q->val
&& isSameTree(p->left, q->left)
&& isSameTree(p->right, q->right));
}
判断两棵树是否互为子树
约定空树不是任意一个树的子结构
bool issub(TreeNode* A, TreeNode* B) {
if (!B) return true;
if (!A) return false;
if (A->val == B->val) return issub(A->left, B->left) && issub(A->right, B->right);
return false;
}
bool isSubStructure(TreeNode* A, TreeNode* B) {
if (!A || !B) return false;
if (issub(A, B)) return true;
return isSubStructure(A->left, B) || isSubStructure(A->right, B);
}
构造二叉树
前序、中序构造二叉树
TreeNode* build(vector<int>&pre, int pl, int pr, vector<int>&in, int il, int ir, map<int, int>&m) {
if (pl > pr || il > ir) return nullptr;
TreeNode *ret = new TreeNode(pre[pl]);
int mid = m[pre[pl]];
ret->left = build(pre, pl+1, pl+mid-il, in, il, mid-1, m);
ret->right = build(pre, pl+mid-il+1, pr, in, mid+1, ir, m);
return ret;
}
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
map<int, int> m;
for (int i = 0; i < inorder.size(); ++i)
m[inorder[i]] = i;
return build(preorder, 0, preorder.size()-1, inorder, 0, inorder.size()-1, m);
}
中序、后续构造二叉树
TreeNode* build(vector<int>&pos, int pl, int pr, vector<int>&in, int il, int ir, map<int, int>&m) {
if (pl > pr || il > ir) return nullptr;
TreeNode *ret = new TreeNode(pos[pr]);
int mid = m[pos[pr]];
ret->left = build(pos, pl, pl+mid-il-1, in, il, mid-1, m);
ret->right = build(pos, pl+mid-il, pr-1, in, mid+1, ir, m);
return ret;
}
TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
map<int, int> m;
for (int i = 0; i < inorder.size(); ++i)
m[inorder[i]] = i;
return build(postorder, 0, postorder.size()-1, inorder, 0, inorder.size()-1, m);
}
二叉树先序展开为链表
直接前序遍历就行,这里展示nb一点的解法
void flatten(TreeNode* root) {
if (!root) return;
TreeNode *next, *pre;
while (root) {
if (root->left) {
next = root->left;
pre = next;
while (pre->right)
pre = pre->right;
if (root->right)
pre->right = root->right;
root->left = nullptr;
root->right = next;
}
root = root->right;
}
}
轴对称翻转二叉树
将树轴对称翻转
TreeNode* dfs(TreeNode*&p) {
if (!p) return nullptr;
TreeNode *l = dfs(p->left);
TreeNode *r = dfs(p->right);
p->left = r;
p->right = l;
return p;
}
TreeNode* invertTree(TreeNode* root) {
dfs(root);
return root;
}
根节点最大二叉树
每次选取数组中最大值作为根节点,递归处理左边数字和右边数字
// 递归 O(n^2)
TreeNode* constructMaximumBinaryTree(vector<int>& nums) {
if (!nums.size()) return nullptr;
auto mid = max_element(nums.begin(), nums.end());
vector<int> leftPart(nums.begin(), mid);
vector<int> rightPart(mid + 1, nums.end());
TreeNode* root = new TreeNode(*mid);
root -> left = constructMaximumBinaryTree(leftPart);
root -> right = constructMaximumBinaryTree(rightPart);
return root;
}
// 单调栈 O(n)
TreeNode* constructMaximumBinaryTree(vector<int>& nums) {
stack<TreeNode*> nodes;
TreeNode* curNode = nullptr;
for (int i=0; i < nums.size(); ++i) {
curNode = new TreeNode(nums[i]);
while (!nodes.empty() && nodes.top()->val < curNode->val) {
TreeNode* top = nodes.top();
nodes.pop();
if (!nodes.empty() && nodes.top()->val < curNode->val)
nodes.top()->right = top;
else
curNode->left = top;
}
nodes.push(curNode);
}
while (!nodes.empty()) {
curNode = nodes.top();
nodes.pop();
if (!nodes.empty())
nodes.top()->right = curNode;
}
return curNode;
}
序列化与反序列化二叉树
void rserialize(TreeNode* root, string& str) {
if (root == nullptr) {
str += "None,";
} else {
str += to_string(root->val) + ",";
rserialize(root->left, str);
rserialize(root->right, str);
}
}
string serialize(TreeNode* root) {
string ret;
rserialize(root, ret);
return ret;
}
TreeNode* rdeserialize(list<string>& dataArray) {
if (dataArray.front() == "None") {
dataArray.erase(dataArray.begin());
return nullptr;
}
TreeNode* root = new TreeNode(stoi(dataArray.front()));
dataArray.erase(dataArray.begin());
root->left = rdeserialize(dataArray);
root->right = rdeserialize(dataArray);
return root;
}
TreeNode* deserialize(string data) {
list<string> dataArray;
string str;
for (auto& ch : data) {
if (ch == ',') {
dataArray.push_back(str);
str.clear();
} else {
str.push_back(ch);
}
}
if (!str.empty()) {
dataArray.push_back(str);
str.clear();
}
return rdeserialize(dataArray);
}
二叉树求解
二叉树的直径
int maxd=0;
int diameterOfBinaryTree(TreeNode* root) {
depth(root);
return maxd;
}
int depth(TreeNode* node) {
if (node == null) return 0;
int Left = depth(node.left);
int Right = depth(node.right);
maxd = max(Left+Right, maxd);
return max(Left, Right)+1;
}
二叉树最大深度
从根节点到最深的叶子节点距离
void dfs(TreeNode *p, int dep, int &ret) {
if (p) ret = max(ret, dep);
else return;
dfs(p->left, dep+1, ret);
dfs(p->right, dep+1, ret);
}
// 距离根节点最远的叶子节点的距离
int maxDepth(TreeNode* root) {
if (!root) return 0;
int ret = 0;
dfs(root, 1, ret);
return ret;
}
二叉树最小深度
从根节点到最浅的叶子节点距离
int minDepth(TreeNode* root) {
queue<TreeNode*> q;
if (!root) return 0;
q.push(root);
int ret = 0;
while (!q.empty()) {
int siz = q.size();
ret++;
while (siz--) {
TreeNode *tmp = q.front();
q.pop();
if (tmp->left) q.push(tmp->left);
if (tmp->right) q.push(tmp->right);
if (!tmp->left && !tmp->right)
return ret;
}
}
return ret;
}
二叉树最大路径
从任意节点出发,到任意节点,至少包含一个节点
int maxGain(TreeNode *p, int &ret) {
if (!p) return 0;
int leftGain = max(maxGain(p->left, ret), 0);
int rightGain = max(maxGain(p->right, ret), 0);
int priceNewpath = p->val + leftGain + rightGain;
ret = max(ret, priceNewpath);
return p->val + max(leftGain, rightGain);
}
int maxPathSum(TreeNode* root) {
int ret = INT_MIN;
maxGain(root, ret);
return ret;
}
二叉树路径总和
判断根节点到叶子节点的和是否等于特定值sum
// DFS
bool hasPathSum(TreeNode *root, int sum) {
if (root == nullptr) {
return false;
}
if (root->left == nullptr && root->right == nullptr) {
return sum == root->val;
}
return hasPathSum(root->left, sum - root->val) ||
hasPathSum(root->right, sum - root->val);
}
// BFS
bool hasPathSum(TreeNode *root, int sum) {
if (root == nullptr) {
return false;
}
queue<TreeNode*> que_node;
queue<int> que_val;
que_node.push(root);
que_val.push(root->val);
while (!que_node.empty()) {
TreeNode *now = que_node.front();
int temp = que_val.front();
que_node.pop();
que_val.pop();
if (now->left == nullptr && now->right == nullptr) {
if (temp == sum) {
return true;
}
continue;
}
if (now->left != nullptr) {
que_node.push(now->left);
que_val.push(now->left->val + temp);
}
if (now->right != nullptr) {
que_node.push(now->right);
que_val.push(now->right->val + temp);
}
}
return false;
}
输出路径
// DFS
vector<vector<int>> ret;
vector<int> path;
void dfs(TreeNode* root, int targetSum) {
if (root == nullptr) {
return;
}
path.emplace_back(root->val);
targetSum -= root->val;
if (root->left == nullptr && root->right == nullptr && targetSum == 0) {
ret.emplace_back(path);
}
dfs(root->left, targetSum);
dfs(root->right, targetSum);
path.pop_back();
}
vector<vector<int>> pathSum(TreeNode* root, int targetSum) {
dfs(root, targetSum);
return ret;
}
输出路径数
// DFS
int rootSum(TreeNode* root, int targetSum) {
if (!root) return 0;
int ret = root->val == targetSum;
ret += rootSum(root->left, targetSum - root->val);
ret += rootSum(root->right, targetSum - root->val);
return ret;
}
int pathSum(TreeNode* root, int targetSum) {
if (!root) return 0;
return rootSum(root, targetSum) + pathSum(root->left, targetSum) + pathSum(root->right, targetSum);
}
// 前缀和
unordered_map<long long, int> prefix;
int dfs(TreeNode *root, long long curr, int targetSum) {
if (!root) return 0;
int ret = 0;
curr += root->val;
if (prefix.count(curr - targetSum)) {
ret = prefix[curr - targetSum];
}
prefix[curr]++;
ret += dfs(root->left, curr, targetSum);
ret += dfs(root->right, curr, targetSum);
prefix[curr]--;
return ret;
}
int pathSum(TreeNode* root, int targetSum) {
prefix[0] = 1;
return dfs(root, 0, targetSum);
}
二叉树的LCA
// 获取从根节点到两个节点的路径,然后判断最早分岔的点
void dfs(TreeNode* p, TreeNode *targe, vector<TreeNode*> &s) {
if (s.size() && s.back() == targe) return;
if (p) {
s.push_back(p);
dfs(p->left, targe, s);
dfs(p->right, targe, s);
if (s.back() != targe) s.pop_back();
}
}
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
vector<TreeNode*> s1, s2;
dfs(root, p, s1);
dfs(root, q, s2);
for (int i = (int)(min(s1.size(), s2.size())-1); i >= 0; --i)
if (s1[i] == s2[i])
return s1[i];
return root;
}
// DFS
bool dfs(TreeNode* root, TreeNode* p, TreeNode* q, TreeNode* &ans) {
if (root == nullptr) return false;
bool lson = dfs(root->left, p, q, ans);
bool rson = dfs(root->right, p, q, ans);
if ((lson && rson) || ((root->val == p->val || root->val == q->val) && (lson || rson))) {
ans = root;
}
return lson || rson || (root->val == p->val || root->val == q->val);
}
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
TreeNode* ans;
dfs(root, p, q);
return ans;
}
// hash
void dfs(TreeNode* root, unordered_map<int, TreeNode*> &fa, unordered_map<int, bool> &vis){
if (root->left != nullptr) {
fa[root->left->val] = root;
dfs(root->left, fa, vis);
}
if (root->right != nullptr) {
fa[root->right->val] = root;
dfs(root->right, fa, vis);
}
}
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
unordered_map<int, TreeNode*> fa;
unordered_map<int, bool> vis;
fa[root->val] = nullptr;
dfs(root, fa, vis);
while (p != nullptr) {
vis[p->val] = true;
p = fa[p->val];
}
while (q != nullptr) {
if (vis[q->val]) return q;
q = fa[q->val];
}
return nullptr;
}