二叉树习题-小记

二叉树

二叉树知识点

在这里插入图片描述
6.偶数个结点:n1=1;奇数个结点n1=0
在这里插入图片描述

相同的树

相同的树
给你两棵二叉树的根节点 p 和 q ,编写一个函数来检验这两棵树是否相同。

如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的。

示例 1:
在这里插入图片描述

输入:p = [1,2,3], q = [1,2,3]
输出:true

示例 2:
在这里插入图片描述

输入:p = [1,2], q = [1,null,2]
输出:false

思路:

  1. 判断根节点(结构和值)
  2. 递归结点p的左树和结点q的左树;
    递归结点p的右树和结点q的右树
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
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;
        }
        //p\q都不为null
        if(p.val!=q.val){
            return false;
        }
        return isSameTree(p.left,q.left)&&isSameTree(p.right,q.right);
        
    }
}

572. 另一棵树的子树

另一棵树的子树
给你两棵二叉树 root 和 subRoot 。检验 root 中是否包含和 subRoot 具有相同结构和节点值的子树。如果存在,返回 true ;否则,返回 false 。

二叉树 tree 的一棵子树包括 tree 的某个节点和这个节点的所有后代节点。tree 也可以看做它自身的一棵子树。

示例 1:
在这里插入图片描述

输入:root = [3,4,5,1,2], subRoot = [4,1,2]
输出:true

示例 2:
在这里插入图片描述

输入:root = [3,4,5,1,2,null,null,null,null,0], subRoot = [4,1,2]
输出:false

思路:

  1. 判断 subRoot是不是和root相同
  2. subRoot是不是root的左子树
  3. subRoot是不是root的右子树
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public boolean isSubtree(TreeNode root, TreeNode subRoot) {
        if(root==null||subRoot==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;
        }
        //p\q都不为null
        if(p.val!=q.val){
            return false;
        }
        return isSameTree(p.left,q.left)&&isSameTree(p.right,q.right);    
    }
}

110. 平衡二叉树

平衡二叉树
给定一个二叉树,判断它是否是高度平衡的二叉树。

本题中,一棵高度平衡二叉树定义为:

一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1 。

示例 1:
在这里插入图片描述

输入:root = [3,9,20,null,null,15,7]
输出:true

示例 2:
在这里插入图片描述

输入:root = [1,2,2,3,3,null,null,4,4]
输出:false

示例 3:

输入:root = []
输出:true

思路:
平衡:每棵子树左右高度差不能超过1

  • root平衡
  • root.left平衡
  • root.right 平衡
    在计算高度时,判断当前的结点是否平衡,若不平衡,向上返回-1.
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public boolean isBalanced(TreeNode root) {
        return maxDepth(root)>=0;
    }
    public int maxDepth(TreeNode root){
        if(root==null){
            return 0;
        }
        int leftH=maxDepth(root.left);
        int leftR=maxDepth(root.right);

        //一个结点左右子树遍历完
        if(leftH>=0&&leftR>=0&&Math.abs(leftH-leftR)<=1){
            return Math.max(leftH,leftR)+1;
        }else{
            return -1;//说明不平衡
        }
    }
}

101. 对称二叉树

对称二叉树

给你一个二叉树的根节点 root , 检查它是否轴对称。

示例 1:
在这里插入图片描述

输入:root = [1,2,2,3,4,4,3]
输出:true

示例 2:
在这里插入图片描述

输入:root = [1,2,2,null,3,null,3]
输出:false

思路:

  1. 判断左树右树是不是对称的
  2. 判断时存在以下情况
  • 1.一个为空,一个不为空
  • 2.两个都为空
  • 3.值是不是一样的
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public boolean isSymmetric(TreeNode root) {
        if(root==null){
            return true;
        }
        //判断左树右树是不是对称的
        return isSymmetricChild(root.left,root.right);

    }
    public boolean isSymmetricChild(TreeNode leftTree,TreeNode rightTree){
        //1.一个为空,一个不为空
        if(leftTree==null&&rightTree!=null||leftTree!=null&&rightTree==null){
            return false;
        }
        //2.两个都为空
        if(leftTree==null&&rightTree==null){
            return true;
        }
        //3.值是不是一样的
        if(leftTree.val==rightTree.val){
            return isSymmetricChild(leftTree.left,rightTree.right)&&isSymmetricChild(leftTree.right,rightTree.left);
        }
        return false;
    }
}

236. 二叉树的最近公共祖先

二叉树的最近公共祖先

思路:

  1. 若p、q在root的左右两边,则root为最近公共祖先。
  2. 若p、q同在左子树,或同在右子树中,则搜索到的返回的第一个结点即为最近公共祖先。
/**
 * 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){
            return null;
        }
        if(root==p||root==q){
            return root;
        }
        TreeNode leftTree=lowestCommonAncestor(root.left,p,q);
        TreeNode rightTree=lowestCommonAncestor(root.right,p,q);
        if(leftTree!=null&&rightTree!=null){
            return root;
        }
        if(leftTree!=null&&rightTree==null){
            return leftTree;
        }
        if(leftTree==null&&rightTree!=null){
            return rightTree;
        }
        return null;
    }
}

1.还可以使用 两个链表求交点(p到公共祖先、q到公共祖先看作两个链表),但前提是每个节点需包含parent域。
2.利用栈,从root节点到p的所有节点插入栈1中,从root节点到q的所有节点放入栈2中,根据栈1和栈2中size的差值,将栈元素数量多的栈元素弹出,直到两个栈中元素数量一致;然后栈1和栈2同时弹出元素,直到弹出的元素相等,即为 【最近公共祖先】

JZ36 二叉搜索树与双向链表

JZ36 二叉搜索树与双向链表

描述
输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。如下图所示
在这里插入图片描述
数据范围:输入二叉树的节点数 0≤n≤1000,二叉树中每个节点的值 0≤val≤1000
要求:空间复杂度O(1)(即在原树上操作),时间复杂度 O(n)

/**
public class TreeNode {
    int val = 0;
    TreeNode left = null;
    TreeNode right = null;

    public TreeNode(int val) {
        this.val = val;

    }

}
*/
public class Solution {
    public TreeNode prev=null;
    public TreeNode Convert(TreeNode pRootOfTree) {
        if(pRootOfTree==null){
            return null;
        }
        ConvertChild(pRootOfTree);

        TreeNode head=pRootOfTree;
        while(head.left!=null){
            head=head.left;
        }
        return head;
    }
    public void ConvertChild(TreeNode pCur){
        if(pCur==null){
            return ;
        }
        ConvertChild(pCur.left);
        pCur.left=prev;
        if(prev!=null){
            prev.right=pCur;
        }
        prev=pCur;
        ConvertChild(pCur.right);
    }
}

105. 从前序与中序遍历序列构造二叉树

从前序与中序遍历序列构造二叉树
关键在于通过preorder得知根结点,在inorder 中找到根节点下标,以此划分左右子树,再根据左右子树下标区间进行递归,来构造二叉树。

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public int preIndex=0;
    public TreeNode buildTree(int[] preorder, int[] inorder) {
        return buildTreeChild(preorder,inorder,0,inorder.length-1);
    }
    public TreeNode buildTreeChild(int[] preorder,int[] inorder,int inbegin,int inend){
        if(inbegin>inend){
            return null;//说明没有左树 或者 没有右树
        }
        TreeNode root=new TreeNode(preorder[preIndex]);

        int rootIndex=findIndex(inorder,preorder[preIndex],inbegin,inend);
        preIndex++;
        root.left=buildTreeChild(preorder,inorder,inbegin,rootIndex-1);
        root.right=buildTreeChild(preorder,inorder,rootIndex+1,inend);
        return root;
    }
    public int findIndex(int[] inorder,int key,int inbegin,int inend){
        for(int i=inbegin;i<=inend;i++){
            if(inorder[i]==key){
                return i;
            }
        }
        return -1;
    }
}

同理106. 从中序与后序遍历序列构造二叉树
从中序与后序遍历序列构造二叉树

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public int postIndex=0;
    public TreeNode buildTree(int[] inorder, int[] postorder) {
        postIndex=postorder.length-1;
        return buildTreeChild(inorder,0,inorder.length-1,postorder);
    }
    public TreeNode buildTreeChild(int[] inorder,int inbegin,int inend,int[] postorder){
        if(inbegin>inend){
            return null;
        }
        TreeNode root=new TreeNode(postorder[postIndex]);

        int rootIndex=findIndex(inorder,inbegin,inend,postorder[postIndex]);
        postIndex--;
        root.right=buildTreeChild(inorder,rootIndex+1,inend,postorder);
        root.left=buildTreeChild(inorder,inbegin,rootIndex-1,postorder);
        return root;
    }
    public int findIndex(int[] inorder,int inbegin,int inend,int key){
        for(int i=inbegin;i<=inend;i++){
            if(inorder[i]==key){
                return i;
            }
        }
        return -1;
    }
}

606 根据二叉树创建字符串

根据二叉树创建字符串

给你二叉树的根节点 root ,请你采用前序遍历的方式,将二叉树转化为一个由括号和整数组成的字符串,返回构造出的字符串。

空节点使用一对空括号对 “()” 表示,转化后需要省略所有不影响字符串与原始二叉树之间的一对一映射关系的空括号对。

给你二叉树的根节点 root ,请你采用前序遍历的方式,将二叉树转化为一个由括号和整数组成的字符串,返回构造出的字符串。

空节点使用一对空括号对 “()” 表示,转化后需要省略所有不影响字符串与原始二叉树之间的一对一映射关系的空括号对。

示例 1:
在这里插入图片描述

输入:root = [1,2,3,4]
输出:“1(2(4))(3)”
解释:初步转化后得到 “1(2(4)())(3()())” ,但省略所有不必要的空括号对后,字符串应该是"1(2(4))(3)" 。

示例 2:
在这里插入图片描述

输入:root = [1,2,3,null,4]
输出:“1(2()(4))(3)”
解释:和第一个示例类似,但是无法省略第一个空括号对,否则会破坏输入与输出一一映射的关系。

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public String tree2str(TreeNode root) {
        StringBuilder sb=new StringBuilder();
        if(root==null){
            return sb.toString();
        }
        tree2strChild(root,sb);
        return new String(sb);
    }
    public 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(")");
        }
    }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
(1)非递归定义 树(tree)是由n(n≥0)个结点组成的有限集合。n=0的树称为空树;n>0的树T: ① 有且仅有一个结点n0,它没有前驱结点,只有后继结点。n0称作树的根(root)结点。 ② 除结点外n0 , 其余的每一个结点都有且仅有一个直接前驱结点;有零个或多个直接后继结点。 (2)递归定义 一颗大树分成几个大的分枝,每个大分枝再分成几个小分枝,小分枝再分成更小的分枝,… ,每个分枝也都是一颗树,由此我们可以给出树的递归定义。 树(tree)是由n(n≥0)个结点组成的有限集合。n=0的树称为空树;n>0的树T: ① 有且仅有一个结点n0,它没有前驱结点,只有后继结点。n0称作树的根(root)结点。 ② 除根结点之外的其他结点分为m(m≥0)个互不相交的集合T0,T1,…,Tm-1,其中每个集合Ti(0≤i<m)本身又是一棵树,称为根的子树(subtree)。 2、掌握树的各种术语: (1) 父母、孩子与兄弟结点 (2) 度 (3) 结点层次、树的高度 (4) 边、路径 (5) 无序树、有序树 (6) 森林 3、二叉树的定义 二叉树(binary tree)是由n(n≥0)个结点组成的有限集合,此集合或者为空,或者由一个根结点加上两棵分别称为左、右子树的,互不相交的二叉树组成。 二叉树可以为空集,因此根可以有空的左子树或者右子树,亦或者左、右子树皆为空。 4、掌握二叉树的五个性质 5、二叉树的二叉链表存储。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值