剑指offer22-23题

第二十二题:二叉搜索树的后序遍历序列

题目描述:输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则输出Yes,否则输出No。假设输入的数组的任意两个数字都互不相同。

首先题目的背景是二叉搜索树。二叉树搜索树又叫二叉排序树,二叉查找树,其有如下性质:

在这里插入图片描述
如上图,根节点的左子树上的所有值都小于根节点的值。根节点右子树上的所有值都大于根节点的值。其左右子树也满足上述规律。

对于二叉搜索树的后序遍历序列,先遍历左子树,再遍历右子树,最后输出根节点的值。
在这里插入图片描述
则输入的数组应该满足上面的性质,我们可以在这个输入的数组中找到根结点的左右子树。当从左向右找到第一个比root大的值的时候,这个值的位置就是根节点右子树的开始位置。此外,我们还需要对这个右子树进行一次遍历,以查看是否有比根节点小的值出现,如果出现了就不满上面说的右子树。

如果满足,则要对根节点的子树进行进一步的判断,所以这是一个递归的过程。
代码如下:

public class Solution {
    public boolean VerifySquenceOfBST(int [] sequence) {
        
        if(sequence == null || sequence.length <=0){
            return false;
        }
        
        //重载原方法,原方法参数不足,不能递归
        return VerifySquenceOfBST(sequence,0,sequence.length-1);
    }
    //重载的方法
    public boolean VerifySquenceOfBST(int [] sequence,int start, int end) {
        //递归的结束条件(剩余结点个数为2或者以下,满足条件)
        if(end - start <=1){
            return true;
        }
        //找到第一个大于根节点值的位置
        while(sequence[start]<sequence[end] && start < end){
            start++;
        }
        //第一段的结束位置
        int center = start - 1;
        
        //判断第二段是否全部大于end的值
        for(int i = start;i<end;i++){
            if(sequence[i] < sequence[end]){
                return false;
            }
        }
        //对左右子树进行判断
        return VerifySquenceOfBST(sequence,0,center) && VerifySquenceOfBST(sequence,start,end-1);
    }
}

第二十三题:二叉树中和为某一值的路径

题目:输入一颗二叉树的根节点和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。(注意: 在返回值的list中,数组长度大的数组靠前)

我们需要定理两个集合,ArrayList<ArrayList> result 用来存储所有的符合条件的路径;ArrayList path,用来存储每一条符合条件路径的结点。同时还要知道当前的结点,以及目标值target。

在这里插入图片描述

如上图所示,对于根节点来说,当前值为10,target为22,故不满足要求。根节点有两条路径可选:左子树和右子树。

由于根节点为10,我们现在需要的target变为22-10 = 12。递归调用方法,传递的参数为子节点、更新后的target 以及用来保存路径的两个集合。同时我们需要把上一个结点加入到路径path中。此外,进入到子树中递归的时候,左右子树分别是两条路径,我们需要分别赋予路径。

递归结束的条件是:
1.结点为空(达不到target值)或者当前结点的值大于target值;
2.当前结点的值等于target值且是叶子结点,则是一条路径,需要将这条路径加入到result 中;若当前结点的值等于target但不是叶子结点,则该路径无效;

其余情况则按照前面所说的流程继续递归。

代码如下:

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

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

    }

}
*/
public class Solution {
    public ArrayList<ArrayList<Integer>> FindPath(TreeNode root,int target) {
        ArrayList<ArrayList<Integer>> result = new ArrayList<ArrayList<Integer>>();
        
        if(root == null || root.val>target){
            return result;
        }
        
        ArrayList<Integer> path = new ArrayList<Integer>();
        
        findPath(root,target,result,path);
        
        return result;
    }
    
    public void findPath(TreeNode root,int target,ArrayList<ArrayList<Integer>> result,ArrayList<Integer> path){
        
        //如果当前结点为空 或者 当前结点值大于target 清空路径
        if(root==null || root.val>target)
        {
            //清空该路径
            path.clear();
        }
        
        else if(root.val == target){
            //达到叶节点,并且路径的值加起来等于target
            if(root.left == null && root.right ==null){
                path.add(root.val);
                result.add(path);
            }
            else{
                //清空该路径
                path.clear();
            }
        }
        
        //如果当前结点值小于target,递归找他的左右子树
        else {
            //先将当前结点加入到路径里面
            path.add(root.val);
            //新创建一条路径,分叉后实际上是两条路径
            ArrayList<Integer> path2=new ArrayList<Integer>();
            path2.addAll(path);
            //此时更新target的值
            target = target - root.val;
            //递归去左右子树中寻找
            findPath(root.left,target,result,path);
            findPath(root.right,target,result,path2);
            
        }

    }
}
发布了12 篇原创文章 · 获赞 6 · 访问量 124

猜你喜欢

转载自blog.csdn.net/qq_38041105/article/details/105266900