一种树递归算法的结构体公式

举例:

输入一棵二叉树的根节点,判断该树是不是平衡二叉树。如果某二叉树中任意节点的左右子树的深度相差不超过1,那么它就是一棵平衡二叉树。

递归/动态规划的思路,在于思考中间状态,递归尤其是要考虑得到的新值与返回值。

对于本题而言,判断平衡二叉树,必须要求所有子树均为平衡二叉树。

在中间状态,需要得到三个值:左子树的高度、右子树的高度、左子树&右子树是否平衡?

需要返回两个值:我本身的高度、我是否平衡?

结构体如下:

    public static class ReturnType{
    
    
    //这就是一个结构体 也就是一个静态类
        public boolean isBalanced;
        public int height;
        //我们需要的是 我本身是否平衡 与 我的高度是多少?
        //ReturnType就是返回的类型
        public ReturnType(boolean isB,int hei)
        {
    
    
            isBalanced = isB;
            height = hei;
            //构造函数构造一下。
        }
    }
        //建造一个返回类型的构造体

在上文的构造体的基础上,我们为之添加递归的条件。

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    
    //递归
    public boolean isBalanced(TreeNode root) {
    
    
        return process(root).isBalanced;
        //主函数,返回的便是ReturnType类中的isBalanced属性
    }
    
   
    public static class ReturnType{
    
    
        public boolean isBalanced;
        public int height;

        public ReturnType(boolean isB,int hei)
        {
    
    
            isBalanced = isB;
            height = hei;
        }
    }
        //建造一个返回类型的构造体

        public static ReturnType process(TreeNode root){
    
    
        //注意 这里返回的是ReturnType类型的 也就是说返回两个值
			if(root==null) return new ReturnType(true,0);//末尾条件
			//递归通常考虑边界条件
			//本题的边界条件便是 root==null 也就是到了空节点
			//我们直接返回true(必然是平衡的)以及0(空树)
			//实际上孩子结点也可以 那样return的就是true和1了
			
			ReturnType leftdata = process(root.left);
			ReturnType rightdata = process(root.right);
			//左右孩子的返回值 ReturnType类型的两个对象
			//接下来我也得返回两个信息

       		int height = Math.max(leftdata.height,rightdata.height)+1;
            //左右孩子更高的那个+1
            boolean isBalanced = leftdata.isBalanced && rightdata.isBalanced && Math.abs(leftdata.height - rightdata.height)<2 ;
            return new ReturnType(isBalanced,height);
            //将ReturnTYpe拆分反悔回去
        }
    }

再来个新例子:
给你一个二叉树的根节点 root ,判断其是否是一个有效的二叉搜索树。

有效 二叉搜索树定义如下:

节点的左子树只包含 小于 当前节点的数。
节点的右子树只包含 大于 当前节点的数。
所有左子树和右子树自身必须也是二叉搜索树。

同样地,我们也需要一个ReturnType类来保存返回值

思考一下,我们如何判断一个树是二叉搜索?那么必须要求:左子树中的最大值小于当前结点,右子树的最小值大于当前结点,左&右子树必须均为二叉搜索树。

这样返回值也就很明确了:该树中的最大值,该树中的最小值,该树是否为搜索树?

    public static class Returndata //注意这里是建立返回值结构体
    {
    
    
        public boolean isBST;
        public int min;
        public int max;
        public Returndata(boolean isBST,int min,int max)
        {
    
    
            this.isBST = isBST;
            this.min = min;
            this.max = max;
        }
    }

然后思考边界条件:叶子结点。
叶子结点的最大最小都是自己,然后必然是二叉搜索树。

接下来,判断的流程是,每次根结点和递归而来的返回值进行比较,校正最大值和最小值之后。然后判断是否符合二叉搜索树,然后返回ReturnType即可。

/**
 * 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 isValidBST(TreeNode root) {
    
    
        return process(root).isBST;
    }

    public static class Returndata //注意这里是建立返回值结构体
    {
    
    
        public boolean isBST;
        public int min;
        public int max;
        public Returndata(boolean isBST,int min,int max)
        {
    
    
            this.isBST = isBST;
            this.min = min;
            this.max = max;
        }

    }

    public static Returndata process(TreeNode root)
    {
    
    
        if(root==null) return null;

        Returndata left = process(root.left);
        Returndata right = process(root.right);
        boolean isbst = true;

        int min = root.val;
        int max = root.val;

        if(right!=null){
    
    
            min = Math.min(right.min,min);
            max = Math.max(right.max,max);
        }

        if(left!=null){
    
    
            min = Math.min(left.min,min);
            max = Math.max(left.max,max);
        }

        if(right!=null)
        {
    
    
           isbst =  right.isBST && right.min>root.val && isbst;
        }
        if(left!=null)
        {
    
    
            isbst = left.isBST && left.max<root.val && isbst;
        }

        return new Returndata(isbst,min,max);


}
}

Guess you like

Origin blog.csdn.net/qq_37772958/article/details/121772201