文章目录[隐藏]
二叉树遍历的非递归实现
先序遍历
stack<TreeNode*> S;
void per(TreeNode* root){
TreeNode* now = root;
while(true){
while(now){
cout << now -> val << '\t';
S.push(now -> right);
now = now -> left;
}
if(S.empty()){
break;
}
now = S.top();
S.pop();
}
}
中序遍历
stack<TreeNode*> S;
void mid(TreeNode* root){
TreeNode* now = root;
while(true){
while(now){
S.push(now);
now = now -> left;
}
if(S.empty()){
break;
}
now = S.top();
S.pop();
cout << now -> val << '\t';
now = now -> right;
}
}
后序遍历
中右左翻转版本:
stack<TreeNode*> S;
void back(TreeNode* root){
TreeNode* now = root;
vector<int> result;
if(!now){
return;
}
S.push(now);
while(!S.empty()){
now = S.top();
S.pop();
result.push_back(now -> val);
if(now -> left){
S.push(now -> left);
}
if(now -> right){
S.push(now -> right);
}
}
reverse(result.begin(), result.end());
for(auto it = result.begin(); it != result.end(); it++){
cout << *it << '\t';
}
}
双指针版本:
stack<TreeNode*> s;
void back(TreeNode* root){
if(root == nullptr){
return;
}
TreeNode *cur = root;
TreeNode *pre = nullptr;
while(cur || !s.empty()){
while(cur){
s.push(cur);
cur = cur -> left;
}
cur = s.top();
//没有右节点或者右节点已输出
if(cur -> right == nullptr || cur -> right == pre){
cout << cur -> val << '\t';
s.pop();
pre = cur;
cur = nullptr;
}else{
cur = cur -> right;
}
}
}
23 真题静态链表版本:
struct{
int Llink;
char data;
int Rlink;
}tree[n];
int s[n + 1];
int t = -1;
p = root;
while(p >= 0 || t >= 0){
if(p >= 0){
t = t + 1;
s[t] = p + 1;//(1)
p = tree[p].Llink;//(2)
}else if(s[t] - 1 >= 0/*(3)*/){
p = tree[s[t] - 1].Rlink;//(4)
s[t] = -s[t];
}else{
cout << tree[-s[t] - 1].data << " ";//(5)
t--;
}
}
二叉树拓展
卡特兰数
设$b_n$表示有$n$个节点的不同的二叉树棵数,当$n> 1$时可以通过递推关系得到:
$$
\begin{cases}
b_0=1& n=0\\
b_n=\sum_{i=0}^{n-1}{b_i\cdot b_{n-i-1},}& n>1\\
\end{cases}
$$
同时可以通过生成函数推得:
$$
b_n=\frac{1}{n+1}C_{2n}^{n}=\frac{1}{n+1}\frac{\left( 2n \right) !}{n!\cdot n!}
$$
它也是$n$个不同元素进栈出栈序列的个数。
int numTrees(int n) {
int dp[n];
memset(dp, 0, sizeof(dp));
int k = 0;
dp[0] = 1;
for(int i = 1;i <= n;i++){
for(int j = 1; j <= i; j++){
dp[i] += dp[i - j] * dp[j - 1];
}
}
return dp[n];
}
二叉树展开为链表
TreeNode* now = nullptr;
void flatten(TreeNode* root) {
if(!root){
return;
}
flatten(root -> right);
flatten(root -> left);
root -> right = now;
root -> left = nullptr;
now = root;
}
二叉树中的最大路径和
int ans;
int find(TreeNode* root) {
if(!root){
return 0;
}else{
int l = find(root -> left),r = find(root -> right);
int a = max(l, 0) + max(r, 0) + root -> val;
int b = root -> val + max(max(l, r), 0);
ans = max(ans, max(a, b));
return b;
}
}
int maxPathSum(TreeNode* root) {
ans = root -> val;
find(root);
return ans;
}
二叉树的最近公共祖先
利用深搜找到通往两个目标节点的路径,从根开始对比两者路径,找到最后一个相同点即是解:
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
vector<TreeNode*> a, b;
dfs(root, p, a); dfs(root, q, b);
TreeNode* ans = nullptr;
for(int i = 0; i < min(a.size(), b.size()) && a[i] == b[i]; i++){
ans = a[i];
}
return ans;
}
bool dfs(TreeNode* cur, TreeNode* t, vector<TreeNode*>& path) {
if(!cur){
return false;
}
path.push_back(cur);
if(cur == t || dfs(cur->left, t, path) || dfs(cur->right, t, path)){
return true;
}else{
path.pop_back();
return false;
}
}
