2021-10-27剑指offer---树(部分题解)

JZ8 二叉树的下一个结点

题目地址
描述
给定一个二叉树其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。注意,树中的结点不仅包含左右子结点,同时包含指向父结点的next指针。下图为一棵有9个节点的二叉树。树中从父节点指向子节点的指针用实线表示,从子节点指向父节点的用虚线表示
在这里插入图片描述
示例:
输入:{8,6,10,5,7,9,11},8
返回:9
解析:这个组装传入的子树根节点,其实就是整颗树,中序遍历{5,6,7,8,9,10,11},根节点8的下一个节点就是9,应该返回{9,10,11},后台只打印子树的下一个节点,所以只会打印9,如下图,其实都有指向左右孩子的指针,还有指向父节点的指针,下图没有画出来
在这里插入图片描述
输入描述:
输入分为2段,第一段是整体的二叉树,第二段是给定二叉树节点的值,后台会将这2个参数组装为一个二叉树局部的子树传入到函数GetNext里面,用户得到的输入只有一个子树根节点
返回值描述:
返回传入的子树根节点的下一个节点,后台会打印输出这个节点
示例1

输入:
{8,6,10,5,7,9,11},8
返回值:
9

示例2

输入:
{8,6,10,5,7,9,11},6
返回值:
7

示例3

输入:
{1,2,#,#,3,#,4},4
返回值:
1

示例4

输入:
{5},5
返回值:
"null"
说明:
不存在,后台打印"null" 

题目思路:
在中序遍历中,求一个结点的后继结点,对于所求结点node,分两种情况讨论:1.node的右子树存在。2.node的右子树不存在。

1. node的右子树存在
node结点的后继结点就是,node右子树的最左节点。
如下图所示:
3号结点的后继结点就是10号结点;
7号结点的后继结点就是9号结点。
在这里插入图片描述

2. node的右子树不存在
node结点的后继结点就是,需要向上寻找父节点,直到满足当前结点是父节点的左子节点。如果不存在满足以上条件的父节点,那么该结点没有后继节点
如下图所示:
5号结点的后继结点 : 1号结点
10号结点的后继结点:8号结点
9号结点的后继节点 :无
在这里插入图片描述
代码:

/*
public class TreeLinkNode {
    int val;
    TreeLinkNode left = null;
    TreeLinkNode right = null;
    TreeLinkNode next = null;

    TreeLinkNode(int val) {
        this.val = val;
    }
}
*/
public class Solution {
    public TreeLinkNode GetNext(TreeLinkNode pNode) {
        if(pNode==null){
            return null;
        }
        if(pNode.right!=null){
            return getMostLeft(pNode.right);
        }else{
            TreeLinkNode pre=pNode.next;//父节点
            TreeLinkNode node=pNode;
            while(pre!=null && pre.left!=node){
                node=pre;
                pre=pre.next;
            }
            return pre;
        }
    }
    public TreeLinkNode getMostLeft(TreeLinkNode node){
        TreeLinkNode res=node;
        while(res.left!=null){
            res=res.left;
        }
        return res;
    }
}

JZ79 平衡二叉树

题目地址
描述
输入一棵节点数为 n 二叉树,判断该二叉树是否是平衡二叉树。
在这里,我们只需要考虑其平衡性,不需要考虑其是不是排序二叉树
平衡二叉树(Balanced Binary Tree),具有以下性质:它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。
样例解释:
在这里插入图片描述
样例二叉树如图,为一颗平衡二叉树
注:我们约定空树是平衡二叉树。

数据范围:n≤100,树上节点的val值满足 0≤val≤1000
要求:空间复杂度O(1),时间复杂度 O(n)
输入描述
输入一棵二叉树的根节点
返回值描述
输出一个布尔类型的值
示例1

输入:
{1,2,3,4,5,6,7}
返回值:
true

示例2

输入:
{}
返回值:
true

代码
一个二叉树的套路题,判断当前树是否是平衡二叉树,只需要知道它的左、右子树是否是平衡二叉树,以及左、右子树的高度信息来更新自己的状态。

import java.util.*;
public class Solution {
    class Result{
        int height;
        boolean isBalanced;
        Result(int height,boolean isBalanced){
            this.height=height;
            this.isBalanced=isBalanced;
        }
    }
    public boolean IsBalanced_Solution(TreeNode root) {
        if(root==null){
            return true;
        }
        Result res=IsBalanced(root);
        return res.isBalanced;
    }
    public Result IsBalanced(TreeNode root){
        if(root==null){
            return new Result(0,true);
        }
        Result left=IsBalanced(root.left);
        Result right=IsBalanced(root.right);
        int height = Math.max(left.height,right.height)+1;
        boolean isBalanced = left.isBalanced && right.isBalanced && Math.abs(left.height-right.height)<=1;
        return new Result(height,isBalanced);
    }
}

JZ36 二叉搜索树与双向链表

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

注意:
1.要求不能创建任何新的结点,只能调整树中结点指针的指向。当转化完成以后,树中节点的左指针需要指向前驱,树中节点的右指针需要指向后继
2.返回链表中的第一个节点的指针
3.函数返回的TreeNode,有左右指针,其实可以看成一个双向链表的数据结构
4.你不用输出双向链表,程序会根据你的返回值自动打印输出
输入描述
二叉树的根节点
返回值描述:
双向链表的其中一个头节点。
示例1

输入:
{10,6,14,4,8,12,16}
返回值:
From left to right are:4,6,8,10,12,14,16;From right to left are:16,14,12,10,8,6,4;
说明:
输入题面图中二叉树,输出的时候将双向链表的头节点返回即可。

示例2

输入:
{5,4,#,3,#,2,#,1}
返回值:
From left to right are:1,2,3,4,5;From right to left are:5,4,3,2,1;
说明:
                    5
                  /
                4
              /
            3
          /
        2
      /
    1
树的形状如上图      

代码
二叉搜索树中序遍历的结果是有序的,因此采用中序遍历的方式。
代码一是中序遍历的非递归形式,代码二是中序遍历的递归形式。
代码一

import java.util.*;
/**
public class TreeNode {
    int val = 0;
    TreeNode left = null;
    TreeNode right = null;

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

    }

}
*/
public class Solution {
    public TreeNode Convert(TreeNode pRootOfTree) {
        TreeNode res=null;
        if(pRootOfTree==null){
            return res;
        }
        TreeNode pre=null;
        TreeNode root=pRootOfTree;
        Stack<TreeNode> stack=new Stack<>();
        while(!stack.isEmpty() || root!=null){
            if(root!=null){
                stack.add(root);
                root=root.left;
            }else{
                root=stack.pop();
                //...
                //System.out.print(" "+root.val);
                root.left=pre;
                //给root的右指针赋值时,一定要注意右指针赋值后,不能影响往后的操作
                //比如给右指针赋值为null,但是之后有用到右指针原来的值的话,会出问题滴
                if(pre==null){
                    res=root;
                }else{
                    pre.right=root;
                }
                pre=root;
                root=root.right;
            }
        }
        return res;
    }
}

代码二

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

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

    }

}
*/
public class Solution {
    TreeNode pre=null;
    TreeNode root=null;
    public TreeNode Convert(TreeNode pRootOfTree) {
        if(pRootOfTree==null){
            return null;
        }
        //递归遍历左子树
        Convert(pRootOfTree.left);
        if(root==null){
            root=pRootOfTree;//结果链表的头结点
        }
        //修改遍历的结点为双向链表
        if(pre!=null){
            pRootOfTree.left=pre;
            pre.right=pRootOfTree;
        }
        //更新pre
        pre=pRootOfTree;
        //递归遍历右子树
        Convert(pRootOfTree.right);
        return root;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值