二叉树-总结例题

1-从中序与后序遍历序列构造二叉树

给定二叉树的后序遍历和二叉树的中序遍历

想法:

  1. 先根据后序遍历的最后一个元素构造根节点
  2. 寻找根节点在中序遍历中的位置
  3. 递归构建根节点的左右子树
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
if(inorder.size() == 0 || postorder.size() == 0)
return NULL;
int _is = 0;
int _ie = inorder.size()-1;
int _ps = 0;
int _pe = postorder.size()-1;
return build(inorder,postorder,_is,_ie,_ps,_pe); }
// 构建节点的递归函数
TreeNode* build(vector<int>& inorder, vector<int>& postorder,int is,int ie,int ps,int pe)
{
// 构建根节点
TreeNode* ans = new TreeNode(postorder[pe]);
int ll = 0;
int rl = 0;
for(int i = is ; i <= ie ; ++i )
{
if(inorder[i] == postorder[pe])
{
// 左子树长度
ll = i - is;
// 右子树长度
rl = ie - i;
}
}
// 构建左子树
if ( ll > 0 )
{
ans->left = build(inorder,postorder,is,is+ll-1,ps,ps+ll-1);
}
// 构建右子树
if ( rl > 0 )
{
ans->right = build(inorder,postorder,ie-rl+1,ie,pe-rl,pe-1);
}
return ans;
}
};

总结:

  1. 返回类型为pointer,异常情况可以直接返回NULL
  2. 上面的代码里用了两个变量,ll和rl分别表示,左右子树在vector里面的长度。
  3. 每次调用递归函数,都用ll和rl改变两个容器的首尾下标。

2-从前序与中序遍历序列构造二叉树

想法:

  1. 先根据先序遍历的最后一个元素构造根节点
  2. 寻找根节点在中序遍历中的位置
  3. 递归构建根节点的左右子树
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
return build(inorder,preorder,0,inorder.size()-1,0,preorder.size()-1);
}
TreeNode* build(vector<int>& inorder,vector<int>& preorder, int is,int ie,int ps,int pe)
{
if(inorder.size()==0 || preorder.size()==0)
{
return NULL;
}
int ll = 0 ;
int rl = 0 ;
TreeNode* ans = new TreeNode(preorder[ps]);
for(int i = is; i<= ie; i++)
{
if(preorder[ps]==inorder[i])
{
ll = i - is ;
rl = ie - i;
}
}
if ( ll > 0 )
{
ans->left = build (inorder,preorder,is,is+ll-1,ps+1 ,ps+ll );
}
if ( rl > 0 )
{
ans->right = build(inorder,preorder,ie-rl+1,ie,pe-rl+1,pe);
}
return ans;
}
};

3-填充每个节点的下一个右侧节点指针(完美二叉树)

想法:

  1. 通过层次遍历,使用队列
  2. 每一层的最后一个节点指向next,否则就指向下一个
class Solution {
public:
Node* connect(Node* root) {
if( root == NULL)
return NULL;
queue<Node*> q;
q.push(root);
// 记录每一层的元素个数
while( ! q.empty())
{
int num = q.size();
// 遍历当前层(队列)里面的每个元素
for(int i = 0; i < num; i++)
{
// p指向 是队列的头节点
Node* p = q.front();
// 出队
q.pop();
// 如果到当前层最后一个元素了,next指针指向NULL,队未空,next指向队头节点
if(i == num-1)
p->next = NULL;
else
p->next = q.front();
// p 的左右孩子节点入队
if( p->left != NULL )
q.push( p->left );
if ( p->right != NULL )
q.push( p->right );
}
}
return root;
}
};

4-填充每个节点的下一个右侧节点指针(非完美二叉树)

我的解法同上。

class Solution {
public:
Node* connect(Node* root) {
if( root == NULL)
return NULL;
queue<Node*> q;
q.push(root);
// 记录每一层的元素个数
while( ! q.empty())
{
int num = q.size();
// 遍历当前层(队列)里面的每个元素
for(int i = 0; i < num; i++)
{
// p指向 是队列的头节点
Node* p = q.front();
// 出队
q.pop();
// 如果到当前层最后一个元素了,next指针指向NULL,队未空,next指向队头节点
if(i == num-1)
p->next = NULL;
else
p->next = q.front();
// p 的左右孩子节点入队
if( p->left != NULL )
q.push( p->left );
if ( p->right != NULL )
q.push( p->right );
}
}
return root;
}
};

5-二叉树的最近公共祖先

自己的想法 :

  1. 在树中分别查找目标节点。把查找的路径存放到两个栈里。
  2. 其中一个栈依次出栈,在另个栈里查找这个出栈的节点。
  3. Note:因为搜索到的路径是唯一的。
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
stack<TreeNode*> A;
stack<TreeNode*> B;
find(root,p,A);
find(root,q,B); vector<int> bb;
for(int i = 0; i< B.size();++i)
{
bb.push_back(B.top()->val);
B.pop();
}
while(!A.empty())
{
TreeNode* ans = A.top();
for(int i = 0 ; i< bb.size();++i)
{
if( ans->val == bb[i])
return ans;
}
}
return NULL;
}
void find (TreeNode* root ,TreeNode* target, stack<TreeNode*> &ss)
{
if (! root)
return ;
if(root->val == target->val)
{
ss.push(root);
}
if(root->left != NULL)
{
vector<int> lv = dfs(root->left);
for(int i = 0; i < lv.size() ; ++i )
{
if(lv[i] == target->val)
{
ss.push(root->left);
find(root->left,target ,ss);
}
}
}
if(root->right != NULL)
{
vector<int> rv = dfs(root->right);
for(int i = 0; i < rv.size() ; ++i )
{
if(rv[i] == target->val)
{
ss.push(root->right);
find(root->right,target,ss);
}
}
}
} vector<int> dfs(TreeNode* root)
{
vector<int> order;
helper(root,order);
return order;
}
void helper( TreeNode* root, vector<int>& vv)
{
if(root->left!=NULL)
helper(root->left,vv);
vv.push_back(root->val);
if(root->right != NULL)
helper(root->right,vv);
}
};
代码超出时间限制

看看人家的代码吧:

/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
if(!root || !p || !q)
return NULL;
vector<TreeNode*> A;
vector<TreeNode*> B;
dfs(root,p,A);
dfs(root,q,B); TreeNode* ans ;
int len = min(A.size(),B.size());
for(int i = 0; i < len ; i++)
{
if(A[i]->val != B[i]->val)
break;
ans = A[i];
}
return ans; }
bool dfs(TreeNode* root,TreeNode* target,vector<TreeNode*>& path)
{
if( root == target ){
path.push_back(root);
return true;
}
path.push_back(root);
if( root->left && dfs( root->left , target,path ))
return true;
if(root->right && dfs( root->right , target , path ))
return true;
// 回溯???
path.pop_back();
return false;
} };

问题:

  1. 在深度遍历函数里,pop_back()的理解:回溯???
  2. for循环的问题
        for(int i = 0; i < len ; i++)
{
if(A[i]->val != B[i]->val)
break;
ans = A[i];
}

LeetCode---二叉树3-总结例题的更多相关文章

  1. LeetCode二叉树实现

    LeetCode二叉树实现 # 定义二叉树 class TreeNode: def __init__(self, x): self.val = x self.left = None self.righ ...

  2. LeetCode 二叉树,两个子节点的最近的公共父节点

    LeetCode 二叉树,两个子节点的最近的公共父节点 二叉树 Lowest Common Ancestor of a Binary Tree 二叉树的最近公共父亲节点 https://leetcod ...

  3. leetcode二叉树题目总结

    leetcode二叉树题目总结 题目链接:https://leetcode-cn.com/leetbook/detail/data-structure-binary-tree/ 前序遍历(NLR) p ...

  4. [LeetCode] 二叉树相关题目(不完全)

    最近在做LeetCode上面有关二叉树的题目,这篇博客仅用来记录这些题目的代码. 二叉树的题目,一般都是利用递归来解决的,因此这一类题目对理解递归很有帮助. 1.Symmetric Tree(http ...

  5. LeetCode二叉树的前序、中序、后序遍历(递归实现)

    本文用递归算法实现二叉树的前序.中序和后序遍历,提供Java版的基本模板,在模板上稍作修改,即可解决LeetCode144. Binary Tree Preorder Traversal(二叉树前序遍 ...

  6. LeetCode 二叉树的层次遍历

    第102题 给定一个二叉树,返回其按层次遍历的节点值. (即逐层地,从左到右访问所有节点). 例如: 给定二叉树: [3,9,20,null,null,15,7], 3 / \ 9 20 / \ 15 ...

  7. LeetCode 二叉树的锯齿形层次遍历

    第103题 给定一个二叉树,返回其节点值的锯齿形层次遍历.(即先从左往右,再从右往左进行下一层遍历,以此类推,层与层之间交替进行). 例如: 给定二叉树 [3,9,20,null,null,15,7] ...

  8. Leetcode——二叉树常考算法整理

    二叉树常考算法整理 希望通过写下来自己学习历程的方式帮助自己加深对知识的理解,也帮助其他人更好地学习,少走弯路.也欢迎大家来给我的Github的Leetcode算法项目点star呀~~ 二叉树常考算法 ...

  9. LeetCode 二叉树的最小深度

    计算二叉树的最小深度.最小深度定义为从root到叶子节点的最小路径. public class Solution { public int run(TreeNode root) { if(root = ...

  10. LeetCode - 二叉树的最大深度

    自己解法,欢迎拍砖 给定一个二叉树,找出其最大深度. 二叉树的深度为根节点到最远叶子节点的最长路径上的节点数. 说明: 叶子节点是指没有子节点的节点. 示例:给定二叉树 [3,9,20,null,nu ...

随机推荐

  1. Exchange Onine 公用文件夹

    公用文件夹专为共享访问设计,为收集.组织信息及工作组织中的其他人共享信息提供提供了一种轻松.有效的方式.公用文件夹帮助以易于浏览的层次结构来组织内容. 一.公用文件夹的适用环境 公用文件夹在以下out ...

  2. 深度优先搜索(DFS)和广度优先搜索(BFS)求解迷宫问题

    用下面这个简单的迷宫图作为例子: OXXXXXXX OOOOOXXX XOXXOOOX XOXXOXXO XOXXXXXX XOXXOOOX XOOOOXOO XXXXXXXO O为通路,X为障碍物. ...

  3. 35)PHP,关于PHP和html

    (1)其实无论是CSS还是js,又或者是html,都是可以随意的载入到我们的php文件中,其实这些文件就是一个外来的引入文件,所以,根本没有什么神奇的, 你要是想把php的结果有调理的展示,那么就直接 ...

  4. Codeforces Round #598 (Div. 3)E(dp路径转移)

    题:https://codeforces.com/contest/1256/problem/E 题意:给一些值,代表队员的能力值,每组要分3个或3个以上的人,然后有个评价值x=(队里最大值-最小值), ...

  5. A. Coffee Break(思维题,类似于邻接表的head数组用法)

    题:https://codeforces.com/gym/101911/problem/A 题意:每天工作m分钟,每次喝coffee得间隔d分钟,然后给出n个数,每个数表示想在一天中的a[i]的时刻喝 ...

  6. Docker系列八: 数据卷

    什么是数据卷 生成环境中使用docker的过程中,往往需要对数据进行持久化,或者需要多个容器之间进行数据共享,这个就涉及到了容器数据管理 容器中管理数据主要有两种方式: 数据卷:容器内数据之间映射到本 ...

  7. 记一次关于JDBCUtils工具类的编写

    jdbc.properties数据库配置的属性文件内容如下 jdbc.driver=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost/xxxx ...

  8. JS创建数组的三种方法

    1     常规方式 创建数组并给数组元素赋值 var myCars = new Array(); myCars[0] = "Saab"; myCars[1] = "Vo ...

  9. nutzboot 项目打包排除或指定配置文件(夹)

    springboot 是一样的 我这里就是从springboot哪里拿过来的 (nutzboot2.x已测试可以使用) 排除指定文件 在pom 文件 build 标签内添加 resources < ...

  10. php中级程序员的进化标准

    1 熟悉linux/unix操作系统,能够写些shell脚本2 能够搭建lamp环境3 熟练使用php,了解或使用过php扩展模块,使用过开源的php框架4 熟悉缓存技术,包括http协议的缓存,利用 ...