1159 Structure of a Binary Tree + 根据前序和中序构建二叉树+ 层序遍历模板复习
Posted 江柏英的技术博客
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了1159 Structure of a Binary Tree + 根据前序和中序构建二叉树+ 层序遍历模板复习相关的知识,希望对你有一定的参考价值。
题目链接:https://pintia.cn/problem-sets/994805342720868352/exam/problems/1478635126488367104
唉,今天的bug出在了下面这条语句。
if (tree[root_key].left * tree[root_key].right < 0) full_tree = false;
我写成了
full_tree = !(tree[root_key].left * tree[root_key].right < 0); // 这就会导致full_tree即便变成了false也有可能变回true。导致错判。
根据前序和中序构建二叉树
参考的柳神代码,灵活的点就在于,用下标表示数组区间,嗯,相比直接传数组的引用,轻了不少。
int build(int R, int start, int end, int fa) // 1. post数组的最右边的位置;2. start, end : in数组的起始位置;3. 对于这题来说还需要记录父节点fa。
if (start > end) return -1;
int root_key = post[R], pos = start;
while (in[pos] != root_key && pos < end) pos++;
tree[root_key].level = tree[fa].level + 1;
tree[root_key].fa = fa;
tree[root_key].left = build(R - 1 - (end - pos), start, pos - 1, root_key); // 记住post的最后一个元素的下标一定要用 R 来相对计算,而不是只用 pos,不然在递归的过程中,即便前几层看不出什么,往后一定会发生错位。
tree[root_key].right = build(R - 1, pos + 1, end, root_key); // 下标的选择是经常容易出bug的,一定要想清楚
if (tree[root_key].left * tree[root_key].right < 0) full_tree = false;
return root_key;
题解代码:
#include<iostream>
#include<vector>
#include<string>
#include<queue>
using namespace std;
int n, m;
struct Node
Node()
fa = left = right = -1;
int level, fa, left, right;
tree[1005];
bool full_tree = true;
int in[35], post[35], num1, num2;
int build(int R, int start, int end, int fa) // 1. post数组的最右边的位置;2. start, end : in数组的起始位置;3. 对于这题来说还需要记录父节点fa。
if (start > end) return -1;
int root_key = post[R], pos = start;
while (in[pos] != root_key && pos < end) pos++;
tree[root_key].level = tree[fa].level + 1;
tree[root_key].fa = fa;
tree[root_key].left = build(R - 1 - (end - pos), start, pos - 1, root_key); // 记住post的最后一个元素的下标一定要用 R 来相对计算,而不是只用 pos,不然在递归的过程中,即便前几层看不出什么,往后一定会发生错位。
tree[root_key].right = build(R - 1, pos + 1, end, root_key); // 下标的选择是经常容易出bug的,一定要想清楚
if (tree[root_key].left * tree[root_key].right < 0) full_tree = false;
return root_key;
bool siblings(int a, int b)
return tree[a].fa == tree[b].fa;
bool same_level(int a, int b)
return tree[a].level == tree[b].level;
bool parent(int a, int b)
return tree[b].fa == a;
bool left_child(int a, int b)
return tree[b].left == a;
bool right_child(int a, int b)
return tree[b].right == a;
int main()
cin >> n;
for (int i = 0; i < n; i++) cin >> post[i];
for (int i = 0; i < n; i++) cin >> in[i];
int root = post[n - 1];
build(n - 1, 0, n - 1, 0);
cin >> m;
while (m--)
string str;
cin >> str;
if (str[0] == \'I\')
getline(cin, str);
cout << (full_tree ? "Yes" : "No") << endl;
else
num1 = stoi(str);
cin >> str;
if (str[0] == \'a\')
cin >> num2 >> str >> str;
if (str[0] == \'s\')
cout << (siblings(num1, num2) ? "Yes" : "No") << endl;
else
getline(cin, str);
cout << (same_level(num1, num2) ? "Yes" : "No") << endl;
else
cin >> str >> str;
switch(str[1])
case \'o\' :
cout << (root == num1 ? "Yes" : "No") << endl;
break;
case \'a\' :
cin >> str >> num2;
cout << (parent(num1, num2) ? "Yes" : "No") << endl;
break;
case \'e\' :
cin >> str >> str >> num2;
cout << (left_child(num1, num2) ? "Yes" : "No") << endl;
break;
case \'i\' :
cin >> str >> str >> num2;
cout << (right_child(num1, num2) ? "Yes" : "No") << endl;
break;
return 0;
刚做的时候以为要用层序遍历,顺便复习一下吧。
层序遍历模板代码:
vector<vector<int>> level_order(Node *root)
vector<vector<int>> res;
queue<Node *> q;
if (root) q.push(root);
while (q.size())
int size = q.size();
vector<int> v;
for (int i = 0; i < size; i++)
Node *node = q.front();
q.pop();
// 上一排的元素依次出队
v.push_back(node->val);
// 下一排的节点全部入队
if (node->left) q.push(node->left);
if (node->right) q.push(node->right);
// 存入一排
res.push_back(v);
return res;
LeetCode 236.lowest-common-ancestor-of-a-binary-tree
题意
给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。
百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
例如,给定如下二叉树: root = [3,5,1,6,2,0,8,null,null,7,4]
示例 1:
输入: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1
输出: 3
解释: 节点 5 和节点 1 的最近公共祖先是节点 3。
示例 2:
输入: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4
输出: 5
解释: 节点 5 和节点 4 的最近公共祖先是节点 5。因为根据定义最近公共祖先节点可以为节点本身。
说明:
所有节点的值都是唯一的。
p、q 为不同节点且均存在于给定的二叉树中。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/lowest-common-ancestor-of-a-binary-tree
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路
从根节点往下遍历,如果当前节点==p或者q,那么直接返回(从上往下找的第一个符合的点必是两点的父亲)。如果当前节点的左子树里有符合条件的点,并且当前节点的右子树也有符合条件的点,那么返回当前节点。如果两个节点的lca出现在左子树或者右子树的一个,那么返回在那个子树找到的结果即可。
时间复杂度O(n),空间复杂度O(n)。
递归很简单。
非递归使用一个HashMap存储每个节点和父亲节点的映射,通过找到p和q的父亲节点,再把p到根节点的路径上的点加入到Set中,最后让q往上爬,找q和p最早相同的节点。
代码
递归:
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if(root==null||root==p||root==q){
return root;
}
TreeNode l=lowestCommonAncestor(root.left,p,q);
TreeNode r=lowestCommonAncestor(root.right,p,q);
if(l!=null&&r!=null){
return root;
}
if(l==null) return r;
return l;
}
}
非递归:
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
Map<TreeNode,TreeNode> fa=new HashMap<>();
fa.put(root,null);
Stack<TreeNode> st=new Stack<>();
st.add(root);
while(!fa.containsKey(p)||!fa.containsKey(q)){
TreeNode cur=st.pop();
if(cur.left!=null){
st.add(cur.left);
fa.put(cur.left,cur);
}
if(cur.right!=null){
st.add(cur.right);
fa.put(cur.right,cur);
}
}
Set<TreeNode> set=new HashSet<>();
while(p!=null){
set.add(p);
p=fa.get(p);
}
while(!set.contains(q)){
q=fa.get(q);
}
return q;
}
}
以上是关于1159 Structure of a Binary Tree + 根据前序和中序构建二叉树+ 层序遍历模板复习的主要内容,如果未能解决你的问题,请参考以下文章
LeetCode 236.lowest-common-ancestor-of-a-binary-tree
Lecture3 Structure of Academic Writing
[Paper] Structure Of The Paper
Structure Of Management Information - SNMP Tutorial
Structure And Representation Of MIB Object Names - SNMP Tutorial