树专题
- Leetcode.297 二叉树的序列化与反序列化 (好难…)
-
中序遍历(栈实现)
stack<TreeNode*>stk;
初始化一个栈
auto p=root;
p指向root节点,不需要先压入栈
while(!stk.empty()||p){
【循环条件】
while(p){
stk.push(p);
p=p->left;
}
auto temp=stk.top();
ans.push_back(temp->val);
stk.pop();
//操作完成后p指向右节点即可
p=temp->right;
}
return ans;
-
层次遍历()
queue<TreeNode*>q;
初始化一个队列
q.push(root);
root入栈
while(!q.empty()){
int size=q.size();
第一步此时的大小for(int i=0;i<size;i++){
TreeNode*temp=q.front();
q.pop();
level.push_back(temp->val);
if(temp->left)q.push(temp->left);
if(temp->right)q.push(temp->right);
}
ans.push_back(level);
}
Leetcode.98验证二叉搜索树 (y总递归参数写的真的优美)
Leetcode.101对称二叉树 (y总递归参数写的真的优美)
Leetcode.94. 二叉树的中序遍历 (模板题)
Leetcode.105从前序与中序遍历序列构造二叉树 (debug了半天)
Leetcode.102. 二叉树的层序遍历 (模板题)
Leetcode.236二叉树的最近公共祖先 (不会)
Leetcode.297 二叉树的序列化与反序列化 (好难…没过)
Leetcode.543二叉树的直径 (还行)
Leetcode.124. 二叉树中的最大路径和 (上一题变式,枚举顶点)
Leetcode.173二叉搜索树迭代器 (值得做,加深对中序遍历的理解)
一、Leetcode.98验证二叉搜索树.
给你一个二叉树的根节点 root ,判断其是否是一个有效的二叉搜索树。
有效 二叉搜索树定义如下:
节点的左子树只包含 小于 当前节点的数。
节点的右子树只包含 大于 当前节点的数。
所有左子树和右子树自身必须也是二叉搜索树。
bool bfs(TreeNode* root,long long min,long long max){
if(root==NULL)return true;
if(root->val<min||root->val>max)return false;
return bfs(root->left,min,root->val-1ll)&& bfs(root->right,root->val+1ll,max);
}
bool isValidBST(TreeNode* root) {
return bfs(root,INT_MIN,INT_MAX);
}
二、Leetcode.101对称二叉树.
给你一个二叉树的根节点 root , 检查它是否轴对称。
bool dfs(TreeNode*p,TreeNode*q){
if(p==NULL){
if(q)return false;
return true;
}
if(q==NULL){
if(p)return false;
}
return p->val==q->val&&dfs(p->left,q->right)&&dfs(q->left,p->right);
}
bool isSymmetric(TreeNode* root) {
if(root==NULL)return true;
return dfs(root->left,root->right);
}
三、Leetcode.94. 二叉树的中序遍历.
给定一个二叉树的根节点 root ,返回 它的 中序 遍历 。
vector<int>ans;
vector<int> inorderTraversal(TreeNode* root) {
stack<TreeNode*>stk;
auto p=root;
while(!stk.empty()||p){
while(p){
stk.push(p);
p=p->left;
}
auto temp=stk.top();
ans.push_back(temp->val);
stk.pop();
p=temp->right;
}
return ans;
}
四、Leetcode.105从前序与中序遍历序列构造二叉树.
给定两个整数数组 preorder 和 inorder ,其中 preorder 是二叉树的先序遍历, inorder 是同一棵树的中序遍历,请构造二叉树并返回其根节点。
unordered_map<int,int>in;
TreeNode* dfs(vector<int>&preorder,vector<int>&inorder,int pl,int pr,int il,int ir){
if(pl>pr)return NULL;
int pos=in[preorder[pl]];//l_length=pos-il
TreeNode*l=dfs(preorder,inorder,pl+1,pl+pos-il,il,il+pos-il-1);
TreeNode*r=dfs(preorder,inorder,pl+pos-il+1,pr,pos+1,ir);
auto root=new TreeNode(preorder[pl]);
root->right=r;
root->left=l;
return root;
}
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
for(int i=0;i<inorder.size();i++)
in[inorder[i]]=i;
return dfs(preorder,inorder,0,inorder.size()-1,0,inorder.size()-1);
}
五、Leetcode.102. 二叉树的层序遍历.
给你二叉树的根节点 root ,返回其节点值的 层序遍历 。 (即逐层地,从左到右访问所有节点)。
vector<vector<int>> levelOrder(TreeNode* root) {
vector<vector<int>>ans;
if(!root)return ans;
queue<TreeNode*>q;
q.push(root);
while(!q.empty()){
int size=q.size();
vector<int>level;
for(int i=0;i<size;i++){
TreeNode*temp=q.front();
q.pop();
level.push_back(temp->val);
if(temp->left)q.push(temp->left);
if(temp->right)q.push(temp->right);
}
ans.push_back(level);
}
return ans;
}
六、Leetcode.236二叉树的最近公共祖先.
给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。
百度百科中最近公共祖先的定义为:“对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
if(root==NULL||root==p||root==q)return root;
TreeNode*r=lowestCommonAncestor(root->right,p,q);
TreeNode*l=lowestCommonAncestor(root->left,p,q);
if(r==NULL)return l;
if(l==NULL)return r;
return root;
}
七、Leetcode.297 二叉树的序列化与反序列化.
序列化是将一个数据结构或者对象转换为连续的比特位的操作,进而可以将转换后的数据存储在一个文件或者内存中,同时也可以通过网络传输到另一个计算机环境,采取相反方式重构得到原数据。
请设计一个算法来实现二叉树的序列化与反序列化。这里不限定你的序列 / 反序列化算法执行逻辑,你只需要保证一个二叉树可以被序列化为一个字符串并且将这个字符串反序列化为原始的树结构。
提示: 输入输出格式与 LeetCode 目前使用的方式一致,详情请参阅 LeetCode 序列化二叉树的格式。你并非必须采取这种方式,你也可以采用其他的方法解决这个问题。
// Encodes a tree to a single string.
string serialize(TreeNode* root) {
string str;
dfs1(root,str);
return str;
}
void dfs1(TreeNode* root,string &str){
if(!root){
str+="#,";
return;
}
str+=to_string(root->val)+',';
dfs1(root->left,str);
dfs1(root->right,str);
}
// Decodes your encoded data to tree.
TreeNode* deserialize(string data) {
int u=0;
return dfs2(data,u);
}
TreeNode* dfs2(string &data,int &u){
if(data[u]=='#'){
u+=2;
return NULL;
}
int t=0;
bool f=false;
if(data[u]=='-'){
f=true;
u++;
}
while(data[u]!=','){
t= t*10+(data[u]-'0');
u++;
}
u++;
if(f)t=-t;
auto root=new TreeNode(t);
root->left=dfs2(data,u);
root->right=dfs2(data,u);
return root;
}
八、Leetcode.543二叉树的直径.
给定一棵二叉树,你需要计算它的直径长度。一棵二叉树的直径长度是任意两个结点路径长度中的最大值。这条路径可能穿过也可能不穿过根结点。
int ans=0;
int dfs(TreeNode*root){
if(root==NULL)return 0;
int l=dfs(root->left);
int r=dfs(root->right);
if(ans<l+r+1)ans=l+r+1;
return max(l,r)+1;
}
int diameterOfBinaryTree(TreeNode* root) {
dfs(root);
return ans-1;
}
九、Leetcode.124二叉树中的最大路径和.
路径 被定义为一条从树中任意节点出发,沿父节点-子节点连接,达到任意节点的序列。同一个节点在一条路径序列中 至多出现一次 。该路径 至少包含一个 节点,且不一定经过根节点。
路径和 是路径中各节点值的总和。
给你一个二叉树的根节点 root ,返回其 最大路径和 。
int ans=-1001;
int dfs(TreeNode* root){
if(!root)return 0;
int right=dfs(root->right);
int left=dfs(root->left);
ans=max(ans,right+left+root->val);
return max(max(0,max(right,left))+root->val,0);
}
int maxPathSum(TreeNode* root) {
dfs(root);
return ans;
}
十、Leetcode.173二叉搜索树迭代器.
实现一个二叉搜索树迭代器类BSTIterator ,表示一个按中序遍历二叉搜索树(BST)的迭代器:
BSTIterator(TreeNode root) 初始化 BSTIterator 类的一个对象。BST 的根节点 root 会作为构造函数的一部分给出。指针应初始化为一个不存在于 BST 中的数字,且该数字小于 BST 中的任何元素。
boolean hasNext() 如果向指针右侧遍历存在数字,则返回 true ;否则返回 false 。
int next()将指针向右移动,然后返回指针处的数字。
注意,指针初始化为一个不存在于 BST 中的数字,所以对 next() 的首次调用将返回 BST 中的最小元素。
你可以假设 next() 调用总是有效的,也就是说,当调用 next() 时,BST 的中序遍历中至少存在一个下一个数字。
stack<TreeNode*>stk;
BSTIterator(TreeNode* root) {
while(root){
stk.push(root);
root=root->left;
}
}
int next() {
auto temp=stk.top();
stk.pop();
auto p=temp->right;
while(p){
stk.push(p);
p=p->left;
}
return temp->val;
}
bool hasNext() {
return !stk.empty();
}