树是一种非线性的数据结构,它是由n ( n>=0)个有限结点组成一个具有层次关系的集合。 把它叫做树是因为它看 起来像一棵倒挂的树,也就是说它是根朝上,而叶朝下的。
它具有以下的特点:
–以下了解即可–
树结构相对线性表就比较复杂了,要存储表示起来就比较麻烦了,实际中树有很多种表示方式,如: 双亲表示法,孩子表示法、孩子双亲表示法、孩子兄弟表示法等等。
我们这里就简单的了解其中最常用的孩子兄弟表示法。
class Node {
int value; // 树中存储的数据
Node firstChild; // 第一个孩子引用
Node nextBrother; // 下一个兄弟引用
}
文件系统管理(目录和文件)
一棵二叉树是结点的一个有限集合,该集合:
二叉树的存储结构分为: 顺序存储和类似于链表的链式存储。
二叉树的链式存储是通过一个一个的节点引用起来的,常见的表示方式有二叉和三叉表示方式,具体如下:
// 孩子表示法
class Node {
int val; // 数据域
Node left; // 左孩子的引用 ,常常代表左孩子为根的整棵左子树
Node right; // 右孩子的引用 ,常常代表右孩子为根的整棵右子树
}
// 孩子双亲表示法
class Node {
int val; // 数据域
Node left; // 左孩子的引用 ,常常代表左孩子为根的整棵左子树
Node right; // 右孩子的引用 ,常常代表右孩子为根的整棵右子树
Node parent; // 当前节点的根节点
}
遍历(Traversal):指沿着某条搜索路线,依次对树中每个结 点均做一次且仅做一次访问。
// 前序遍历
void preOrder(Node root);
// 中序遍历
void inOrder(Node root);
// 后序遍历
void postOrde(Node root);
public class BinaryTree {
static class TreeNode{
public char val;
public TreeNode left;
public TreeNode right;
public TreeNode(char val){
this.val=val;
}
}
//这个二叉树的根节点
public TreeNode root;
//创建一颗树
public void createTree(){
TreeNode A=new TreeNode('A');
TreeNode B=new TreeNode('B');
TreeNode C=new TreeNode('C');
TreeNode D=new TreeNode('D');
TreeNode E=new TreeNode('E');
TreeNode F=new TreeNode('F');
TreeNode G=new TreeNode('G');
TreeNode H=new TreeNode('H');
A.left=B;
A.right=C;
B.left=D;
C.left=F;
C.right=G;
E.right=H;
this.root=A;
}
}
//前序遍历
void preOrder(TreeNode root){
if(root==null) return;
System.out.println(root.val+" ");
preOrder(root.left);
preOrder(root.right);
}
题目》》
2、这里不能返回null,必须返回ret,由测试用例可知
class Solution {
List<Integer> ret=new ArrayList<>();
public List<Integer> preorderTraversal(TreeNode root) {
if(root==null)return ret;//这里不能返回null,必须返回ret,由测试用例可知
ret.add(root.val);
preorderTraversal(root.left);
preorderTraversal(root.right);
return ret;
}
}
//中序遍历
void inOrder(TreeNode root){
if(root==null) return;
inOrder(root.left);
System.out.println(root.val+" ");
inOrder(root.right);
}
题目》》
class Solution {
List<Integer> ret=new ArrayList<>();
public List<Integer> inorderTraversal(TreeNode root) {
if(root==null)return ret;
inorderTraversal(root.left);
ret.add(root.val);
inorderTraversal(root.right);
return ret;
}
}
//后序遍历
void postOrder(TreeNode root){
if(root==null) return;
postOrder(root.left);
postOrder(root.right);
System.out.println(root.val+" ");
}
题目》》
class Solution {
List<Integer> ret=new ArrayList<>();
public List<Integer> postorderTraversal(TreeNode root) {
if(root==null)return ret;
postorderTraversal(root.left);
postorderTraversal(root.right);
ret.add(root.val);
return ret;
}
}
本题采用非递归的方式进行层序遍历。使用队列来实现。
先判断根节点是否为空,如果不为空就入队,接着再把根节点的左右子树入队,然后都出队,
//层序遍历
//可以引伸出的题目
//求树的最大宽度,求树的左视图
void levelOrder2(TreeNode root){
if(root==null)return;
Queue<TreeNode> queue=new LinkedList<>();
queue.offer(root);
while(!queue.isEmpty()){
TreeNode cur=queue.poll();
System.out.println(cur.val+" ");//如果不为空,就放到队列里面,然后弹出去,在打印它
if(cur.left!=null){
queue.offer(cur.left);
}
if(cur.right!=null){
queue.offer(cur.right);
}
}
}
class Solution{
public List<Integer> rightSideView(TreeNode root){
List<Integer> res=new ArrayList<>();//res里面存放右视图的节点
if(root==null){
return res;//如果结点是空,直接返回null的res
}
Queue<TreeNode>queue=new LinkedList<>();
queue.offer(root);
while(!queue.isEmpty()){
int size=queue.size();
for(int i=0;i<size;i++){ //遍历当前层的所有节点
TreeNode node=queue.poll();
if(node.left!=null){
queue.offer(node.left);//将当前节点的左孩子入队
}
if(node.right!=null){
queue.offer(node.right);//将当前节点的右孩子入队
}
if(i==size-1){ //将当前层的最后一个节点放入结果列表
res.add(node.val);
}
}
}
return res;
}
}
题目》》》》》》》》》》》》》》》》》》》》》
在这里插入代码片
题目》》》》》》》》》》》》》》》
class Solution {
public List<List<Integer>> levelOrder(TreeNode root) {
List<List<Integer>> ret = new ArrayList<>();
if (root == null) return ret;
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
while (!queue.isEmpty()) {
int size = queue.size();
List<Integer> row = new ArrayList<>();
while (size > 0) {
TreeNode cur = queue.poll();
size--;
row.add(cur.val);
if (cur.left != null) {
queue.offer(cur.left);
}
if (cur.right != null) {
queue.offer(cur.right);
}
}
ret.add(row);
}
return ret;
}
}
//子问题思路 获取树中节点个数
int size(TreeNode root){
if(root==null) return 0;
return size(root.left)+size(root.right)+1;
}
//获取树当中节点的个数:只要遍历到了节点就++
public static int nodeSize;
void size2(TreeNode root){
if(root==null) return;
nodeSize++;
size2(root.left);
size2(root.right);
}
//子问题 获取叶子节点的个数
int getLeafNodeCount(TreeNode root){
if(root==null)return 0;//说明无叶子节点
if(root.left==null && root.right==null)return 1;
return getLeafNodeCount(root.right)+getLeafNodeCount(root.left);
}
//获取树当中叶子节点的个数
public static int leafsize;
void getLeafNodeCount2(TreeNode root){
if(root==null) return;
if(root.left==null && root.right==null)leafsize++;
getLeafNodeCount2(root.left);
getLeafNodeCount2(root.right);
}
//求第K层节点的个数
int getKLevelNodeCount(TreeNode root,int k){
if(root==null)return 0;
if(k==1)return 1;
return getKLevelNodeCount(root.left,k-1)+getKLevelNodeCount(root.right,k-1);
}
题目》》》》》》》》》》》》》》》》》》》》》》》》》》
分析:树的高度是【左树和右树高度的最大值】+1
//获取二叉树的高度
int getHeight(TreeNode root){
if(root==null)return 0;
return 1+getHeight(root.right)>getHeight(root.left)?getHeight(root.right):getHeight(root.left);
}
但是上面的代码在OS题目上面无法通过,超出了时间限制。改成一下代码即可:
//获取二叉树的高度
int getHeight(TreeNode root){
if(root==null)return 0;
int leftHeight=getHeight(root.left);
int rightHeight=getHeight(root.right);
return 1+leftHeight > rightHeight ? leftHeight : rightHeight;
}
找根节点和左右子树中是否存在该节点,如果没有的话就返回null
//查找当前树当做是否存在该节点
TreeNode find(TreeNode root,int val){
if(root==null)return null;
if(root.val==val)return root;
TreeNode ret1=find(root.left,val);//用一个节点接收查找左子树得到的返回值
if(ret1!=null) return ret1;//说明在左子树当中找到这个值了
TreeNode ret2=find(root.right,val);//用一个节点接收查找右子树得到的返回值
if(ret2!=null) return ret2;//说明在右子树当中找到这个值了
return null;//说明在根节点和左右子树都没有找到这个结点
}
// 判断一棵树是不是完全二叉树
boolean isCompleteTree(TreeNode root) {
if(root==null)return true;//空树也是一棵完全二叉树
Queue<TreeNode> queue=new LinkedList<>();
queue.offer(root);
while(!queue.isEmpty()){
TreeNode cur=queue.poll();
if(cur!=null){
//这里和层序遍历不同,只要cur不是空的,则左右子节点都入队
queue.offer(cur.left);
queue.offer(cur.right);
}else{
break;
}
}
while(!queue.isEmpty()){
TreeNode cur=queue.peek();
if(cur!=null){
return false;
}else{
queue.poll();
}
}
return true;
}
import com.sun.source.tree.Tree;
import java.util.LinkedList;
import java.util.Queue;
/**
* @author Susie-Wen
* @version 1.0
* @description:
* @date 2022/7/13 12:30
*/
public class BinaryTree {
static class TreeNode {
public char val;
public TreeNode left;//左孩子的引用
public TreeNode right;//右孩子的引用
public TreeNode(char val) {
this.val = val;
}
}
/**
* 创建一棵二叉树 返回这棵树的根节点
*
* @return
*/
public TreeNode createTree() {
TreeNode A=new TreeNode('A');
TreeNode B=new TreeNode('B');
TreeNode C=new TreeNode('C');
TreeNode D=new TreeNode('D');
TreeNode E=new TreeNode('E');
TreeNode F=new TreeNode('H');
TreeNode G=new TreeNode('G');
TreeNode H=new TreeNode('H');
A.left=B;
A.right=C;
B.left=D;
B.right=E;
C.left=F;
C.right=G;
E.right=H;
return A;
}
// 前序遍历
public void preOrder(TreeNode root) {
if(root==null)return;
System.out.print(root.val+" ");
preOrder(root.left);
preOrder(root.right);
}
// 中序遍历
void inOrder(TreeNode root) {
if(root==null)return;
preOrder(root.left);
System.out.print(root.val+" ");
preOrder(root.right);
}
// 后序遍历
void postOrder(TreeNode root) {
if(root==null)return;
preOrder(root.left);
preOrder(root.right);
System.out.print(root.val+" ");
}
public static int nodeSize;
/**
* 获取树中节点的个数:遍历思路
*/
void size(TreeNode root) {
if(root==null)return;
nodeSize++;
size(root.left);
size(root.right);
}
/**
* 获取节点的个数:子问题的思路
*
* @param root
* @return
*/
int size2(TreeNode root) {
if(root==null)return 0;
return size2(root.left)+size2(root.right)+1;
}
/*
获取叶子节点的个数:遍历思路
*/
public static int leafSize = 0;
void getLeafNodeCount1(TreeNode root) {
if(root==null)return;
if(root.left==null&&root.right==null) {
leafSize++;
}
getLeafNodeCount1(root.left);
getLeafNodeCount1(root.right);
}
/*
获取叶子节点的个数:子问题
*/
int getLeafNodeCount2(TreeNode root) {
if(root==null)return 0;
if(root.left==null&&root.right==null)return 1;
return getLeafNodeCount2(root.left)+getLeafNodeCount2(root.right);
}
/*
获取第K层节点的个数
*/
int getKLevelNodeCount(TreeNode root, int k) {
if(root==null)return 0;
if(k==1)return 1;
return getKLevelNodeCount(root.left,k-1)+getKLevelNodeCount(root.right,k-1);
}
/*
获取二叉树的高度
时间复杂度:O(N)
*/
int getHeight(TreeNode root) {
if(root==null)return 0;
int leftHeight=getHeight(root.left);
int rightHeight=getHeight(root.right);
return 1+Math.max(leftHeight,rightHeight);
}
// 检测值为value的元素是否存在
TreeNode find(TreeNode root, char val) {
if(root.val==val)return root;
TreeNode leftNode=find(root.left,val);
if(leftNode!=null)return leftNode;
TreeNode rightNode=find(root.right,val);
if(rightNode!=null)return rightNode;
return null;
}
//层序遍历
void levelOrder(TreeNode root) {
if(root==null)return;
Queue<TreeNode> queue=new LinkedList<>();
queue.offer(root);
while(!queue.isEmpty()){
TreeNode cur=queue.poll();
System.out.println(cur.val+" ");
if(cur.left!=null)queue.offer(cur.left);
if(cur.right!=null)queue.offer(cur.right);
}
}
// 判断一棵树是不是完全二叉树
boolean isCompleteTree(TreeNode root) {
if(root==null)return true;//空树也是一棵完全二叉树
Queue<TreeNode> queue=new LinkedList<>();
queue.offer(root);
while(!queue.isEmpty()){
TreeNode cur=queue.poll();
if(cur!=null){
queue.offer(cur.left);
queue.offer(cur.right);
}else{
break;
}
}
while(!queue.isEmpty()){
TreeNode cur=queue.peek();
if(cur!=null){
return false;
}else{
queue.poll();
}
}
return true;
}
}
public class Test02 {
public static void main(String[] args) {
BinaryTree binaryTree=new BinaryTree();
BinaryTree.TreeNode root=binaryTree.createTree();
System.out.println("前序遍历");
binaryTree.preOrder(root);
System.out.println();
System.out.println("中序遍历");
binaryTree.inOrder(root);
System.out.println();
System.out.println("后序遍历");
binaryTree.postOrder(root);
System.out.println();
System.out.println("节点个数1:"+binaryTree.size2(root));
System.out.println("高度:"+binaryTree.getHeight(root));
System.out.println("层序遍历");
binaryTree.levelOrder(root);
System.out.println("是否是完全二叉树");
System.out.println(binaryTree.isCompleteTree(root));
}
}
解:B,对于二叉树来说,叶子节点的个数是度为2节点个数+1。
解:A,n0+n1+n2=2n,n0+n1+n0-1=2n,2*n0+n1=2n+1,则n0=n。
解:B,n0+n1+n2=767,n0+n1+n0-1=767,n0*2+n1=768==>n1=0,n0=384
解:B,K=向上取整【log2(n+1)】
解:A
解:A
解:D
解:A
题目》》》》》》》》》》》》》》》
给你两棵二叉树的根节点 p 和 q ,编写一个函数来检验这两棵树是否相同。如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的。
分析:可能出现的情况
使用前序遍历来检查:当根节点一样,并且左右子树也相同,则两棵树就相同。
这里使用的前序遍历,就是深度优先算法。
下面的if语句不能交换,如果第二个if和第三个if交换的话会出现空指针异常。
时间复杂度:O(min (m,n) ),因为当有一个节点不同的时候,就返回false了。
class Solution {
public boolean isSameTree(TreeNode p, TreeNode q) {
if(p==null && q!=null || p!=null && q==null)return false;
if(p==null && q==null)return true;
if(p.val != q.val)return false;
// p!=null && q!=null && p.val!=q.val
return isSameTree(p.left,q.left) && isSameTree(p.right,q.right);
}
}
题目》》》》》》》》》》》》》》
分析:情况如下
时间复杂度:O(m*n)因为root的每一个节点都需要和subRoot的节点进行比较。
isSubtree方法当中,需要最先判断两棵树是否有一个是null,只要有一个为空,就返回false。
这里使用的方法isSameTree就是上一题当中的代码。
class Solution {
public boolean isSubtree(TreeNode root, TreeNode subRoot) {
if(root==null)return false;//否则会出现空指针异常
if(isSameTree(root,subRoot))return true;
if(isSubtree(root.left,subRoot))return true;
if(isSubtree(root.right,subRoot))return true;
return false;//都不满足
}
public boolean isSameTree(TreeNode p, TreeNode q){
if(p==null && q!=null || p!=null && q==null)return false;
if(p==null && q==null)return true;
if(p.val != q.val)return false;
// p!=null && q!=null && p.val!=q.val
return isSameTree(p.left,q.left) && isSameTree(p.right,q.right);
}
}
题目》》》》》》》》》》》》
class Solution {
public int maxDepth(TreeNode root) {
if(root==null)return 0;
int leftHeight=maxDepth(root.left);
int rightHeight=maxDepth(root.right);
return leftHeight>rightHeight?leftHeight+1:rightHeight+1;
}
}
题目》》》》》》》》》》
给定一个二叉树,判断它是否是高度平衡的二叉树。
本题中,一棵高度平衡二叉树定义为:一个二叉树每个节点的左右两个子树的高度差的绝对值不超过 1 。
分析:
时间复杂度:O(n^2)
class Solution {
public boolean isBalanced(TreeNode root) {
if(root==null)return true;
if(Math.abs(maxDepth(root.left)-maxDepth(root.right))<=1
&& isBalanced(root.left) && isBalanced(root.right))return true;
return false;
}
public int maxDepth(TreeNode root) {
if(root==null)return 0;
int leftHeight=maxDepth(root.left);
int rightHeight=maxDepth(root.right);
return leftHeight>rightHeight?leftHeight+1:rightHeight+1;
//return Math.max(leftHeight,rightHeight)+1;
}
}
上面代码的复杂度太大,在面试的时候肯定不行的,因此需要改进。
时间复杂度:O(n)
class Solution {
public boolean isBalanced(TreeNode root) {
if(root==null)return true;
return maxDepth(root)>=0;
}
public int maxDepth(TreeNode root) {
if(root==null)return 0;
int leftHeight=maxDepth(root.left);
int rightHeight=maxDepth(root.right);
if(leftHeight>=0 && rightHeight>=0 &&
Math.abs(leftHeight-rightHeight)<=1)return Math.max(leftHeight,rightHeight)+1;
else return -1;//出现不平衡则最终高度会返回-1
}
}
题目》》》》》》》》》》》》》》》》》
分析:要判断root这棵树是否对称,我们需要判断root的左树和右树是否的对称的。都要判断null。
class Solution {
public boolean isSymmetric(TreeNode root) {
if(root==null)return true;
return isSymmetricChild(root.left,root.right);
}
private boolean isSymmetricChild(TreeNode leftTree,TreeNode rightTree){
if(leftTree==null && rightTree!=null || leftTree!=null && rightTree==null)return false;
if(leftTree==null && rightTree==null)return true;
if(leftTree.val!=rightTree.val)return false;
return isSymmetricChild(leftTree.left,rightTree.right) &&
isSymmetricChild(leftTree.right,rightTree.left);
}
}
编一个程序,读入用户输入的一串先序遍历字符串,根据此字符串建立一个二叉树(以指针方式存储)。 例如如下的先序遍历字符串: ABC##DE#G##F### 其中“#”表示的是空格,空格字符代表空树。建立起此二叉树以后,再对二叉树进行中序遍历,输出遍历结果。
题目》》》》》》》》》》》》》》》》》》》》》》》
import java.util.*;
class TreeNode{
public char val;
public TreeNode left;
public TreeNode right;
public TreeNode(char val){this.val=val;}
}
public class Main{
public int i=0;
//创建二叉树
public TreeNode createTree(String s){
TreeNode root=null;
if(s.charAt(i)!='#'){
root=new TreeNode(s.charAt(i));
i++;
root.left=createTree(s);
root.right=createTree(s);
}else{
i++;
}
return root;
}
public static void inorder(TreeNode root){
if(root==null) return;
inorder(root.left);
System.out.print(root.val+" ");
inorder(root.right);
}
public static void main(String[] args){
Scanner scan=new Scanner(System.in);
while(scan.hasNextLine()){
String s=scan.nextLine();
Main m=new Main();
TreeNode root=m.createTree(s);
m.inorder(root);
}
}
}
给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。
百度百科中最近公共祖先的定义为:“对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
题目》》》》》》》》》》》》》》》》》》》》》
分析:
class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if(root==null)return null;
if(root==p || root==q)return root;
TreeNode retleft=lowestCommonAncestor(root.left,p,q);
TreeNode retright=lowestCommonAncestor(root.right,p,q);
if(retleft !=null && retright !=null)return root;
else if(retleft!=null)return retleft;
else return retright;
}
}
把从根节点到指定节点的路径存储到栈中: 遇到节点就放到栈里面,然后判断放到栈中的元素是否是指定节点,如果不是指定节点的话,就递归左子树和右子树,如果都没有的话就都出栈。
class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if(root==null || p==null || q==null)return null;
Stack<TreeNode> stack1=new Stack<>();
getPath(root,p,stack1);
Stack<TreeNode> stack2=new Stack<>();
getPath(root,q,stack2);
int size1=stack1.size();
int size2=stack2.size();//比较两个栈谁大谁小,多元素的那个栈要先出栈一些元素,直到所有的元素都相等
if(size1>size2){
int tmp=size1-size2;
while(tmp!=0){
stack1.pop();
tmp--;
}
}else{
int tmp=size2-size1;
while(tmp!=0){
stack2.pop();
tmp--;
}
}
//此时两个栈当中,元素个数一样的
while(!stack1.empty() && !stack2.empty()){
if(stack1.peek() == stack2.peek()){
return stack1.peek();
}else{
stack1.pop();
stack2.pop();
}
}
return null;//没有公共祖先
}
//找到根节点到指定节点node之间路径上的所有节点,存储到stack当中。
private boolean getPath(TreeNode root,TreeNode node,Stack<TreeNode> stack){
if(root==null || node==null)return false;
stack.push(root);
if(root==node)return true;
boolean ret1=getPath(root.left,node,stack);
//此时还不能直接判断false,因为此时只能证明左边不存在
if(ret1==true)return true;
boolean ret2=getPath(root.right,node,stack);
if(ret2==true)return true;
//根节点和左右子树都不是,因此出栈
stack.pop();
return false;
}
}
题目》》》》》》》》》》》》》》》》》》》》
输入一棵二叉搜索树,将该二叉搜索树转换成一个 排序 的双向链表。
分析:
pRootOfTree
指向的是二叉搜索树的根节点,因此还要向左遍历,直到找到头结点。public class Solution {
public TreeNode prev=null;
public void ConvertChild(TreeNode root){
//中序遍历
if(root==null)return;
ConvertChild(root.left);
// System.out.println(root.val+" ");
root.left=prev;
if(prev!=null){
prev.right=root;
}
prev=root;
ConvertChild(root.right);
}
public TreeNode Convert(TreeNode pRootOfTree) {
if(pRootOfTree==null)return null;
ConvertChild(pRootOfTree);
//向左遍历找到双向链表的头结点
TreeNode head=pRootOfTree;
while(head.left!=null){
head=head.left;
}
return head;
}
}
给定两个整数数组 preorder 和 inorder ,其中 preorder 是二叉树的先序遍历, inorder 是同一棵树的中序遍历,请构造二叉树并返回其根节点。
题目》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》
分析:
class Solution {
public int preIndex=0;
private TreeNode buildTreeChild(int[] preorder,int[] inorder,int inbegin,int inend){
if(inbegin>inend)return null;//没有左树或者没有右树
TreeNode root=new TreeNode(preorder[preIndex]);//构建根节点
//找到当前根节点在中序遍历中的位置
int rootIndex=findInorderIndex(inorder,preorder[preIndex],inbegin,inend);
preIndex++;
root.left=buildTreeChild(preorder,inorder,inbegin,rootIndex-1);
root.right=buildTreeChild(preorder,inorder,rootIndex+1,inend);
return root;
}
private int findInorderIndex(int[] inorder,int val,int inbegin,int inend){
for(int i=inbegin;i<=inend;i++){
if(inorder[i]==val)return i;
}
return -1;
}
public TreeNode buildTree(int[] preorder, int[] inorder) {
return buildTreeChild(preorder,inorder,0,inorder.length-1);
}
}
题目》》》》》》》》》》》》》》》》
class Solution {
public int postIndex=0;
private TreeNode buildTreeChild(int[] postorder,int[] inorder,int inbegin,int inend){
if(inbegin>inend)return null;//没有左树或者没有右树
TreeNode root=new TreeNode(postorder[postIndex]);//构建根节点
//找到当前根节点在中序遍历中的位置
int rootIndex=findInorderIndex(inorder,postorder[postIndex],inbegin,inend);
postIndex--;
root.right=buildTreeChild(postorder,inorder,rootIndex+1,inend);
root.left=buildTreeChild(postorder,inorder,inbegin,rootIndex-1);
return root;
}
private int findInorderIndex(int[] inorder,int val,int inbegin,int inend){
for(int i=inbegin;i<=inend;i++){
if(inorder[i]==val)return i;
}
return -1;
}
public TreeNode buildTree(int[] inorder, int[] postorder) {
postIndex=postorder.length-1;
return buildTreeChild(postorder,inorder,0,inorder.length-1);
}
}
题目》》》》》》》》》》》》》》》》》》
class Solution {
public String tree2str(TreeNode root) {
StringBuilder sb=new StringBuilder();
tree2strChild(root,sb);
return sb.toString();
}
private void tree2strChild(TreeNode t,StringBuilder sb){
if(t==null)return;
sb.append(t.val);//把根节点放到字符串里面
if(t.left!=null){
sb.append("(");
//递归左树
tree2strChild(t.left,sb);
sb.append(")");
}else{
if(t.right==null){
return;
}else{
sb.append("()");//左边没有子树,右边有子树的情况
}
}
if(t.right==null){
return;
}else{
sb.append("(");
//递归右树
tree2strChild(t.right,sb);
sb.append(")");
}
}
}
题目》》》》》》》》》》》》》》》》》》》》
class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
Stack<TreeNode> stack=new Stack<>();
List<Integer> ret=new ArrayList<>();
TreeNode cur=root;
while(cur!=null || !stack.empty()){
while(cur!=null){
stack.push(cur);
System.out.print(cur.val+" ");
ret.add(cur.val);
cur=cur.left;
}
//如果cur为空,就从栈当中弹出一个元素,赋给top,并遍历top的右边
TreeNode top=stack.pop();
cur=top.right;
}
return ret;
}
}
题目》》》》》》》》》》
class Solution {
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> ret=new ArrayList<>();
Stack<TreeNode> stack=new Stack<>();
TreeNode cur=root;
while(cur!=null || !stack.empty()){
while(cur!=null){
stack.push(cur);
cur=cur.left;
}
//如果cur为空,就从栈当中弹出一个元素,赋给top,并遍历top的右边
TreeNode top=stack.pop();
ret.add(top.val);
cur=top.right;
}
return ret;
}
}
题目》》》》》》》》》》》》》》》》》》》》
class Solution {
public List<Integer> postorderTraversal(TreeNode root) {
List<Integer> ret=new ArrayList<>();
Stack<TreeNode> stack=new Stack<>();
TreeNode prev=null;
TreeNode cur=root;
while(cur!=null || !stack.empty()){
while(cur!=null){
stack.push(cur);
cur=cur.left;
}
//如果cur为空,就从栈当中弹出一个元素,赋给top,并遍历top的右边
TreeNode top=stack.peek();
if(top.right==null || top.right==prev){//右边为空,或者右边已经打印过了
stack.pop();
ret.add(top.val);
prev=top;
}else{
cur=top.right;
}
}
return ret;
}
}
题目》》》》》》》》》》》》》》》》》》》》》》》》》
可以参考第七题的对称二叉树
class Solution {
public TreeNode invertTree(TreeNode root) {
if(root==null)return null;
return reverseTree(root);
}
public TreeNode reverseTree(TreeNode root){
if(root==null)return null;
TreeNode t=root.left;
root.left=root.right;
root.right=t;
reverseTree(root.left);
reverseTree(root.right);
return root;
}
}