Fork me on GitHub

前序遍历二叉搜索树

⭐前序遍历搜索二叉树

思路

将搜索二叉树前序遍历排序便得到该搜索二叉树的中序遍历,根据前序和中序遍历递归构造二叉树即可。

思路误区

  1. 排序后误将中序遍历的中间值作为根节点构造二叉树
  2. 递归到剩下3个节点可以继续递归
  3. 没次递归没有处理好下一次递归需要的前序和中序遍历数组。导致出错。
  4. 递归右子树时应该判断index+1小于中序遍历数组长度,否则会多加上值为0的多余节点。

自己实现的代码(中间玩游戏下班写了2天,一直出错,效率低下)

package com.gml.test01;

import java.util.Arrays;

/**
 * @description:
 *
 * @author: gml
 * @date: 2022-03-23 20:54
 */

public class test01 {
    public static void main(String[] args) {
        int[] param={7,2,20,12,8};
        TreeNode node=bstFromPreorder(param);
        System.out.println(node);
    }
    public static TreeNode bstFromPreorder(int[] preorder) {
        TreeNode node=new TreeNode();
        int[] sort=Arrays.copyOf(preorder,preorder.length);
        Arrays.sort(sort);
        return bulid(sort,node,preorder);
    }

    private static TreeNode bulid(int[] order,TreeNode node,int[] origin){

        if(origin.length==2){
            int index1=getIndex(origin,order[0]);
            int index2=getIndex(origin,order[1]);
            if(index1>index2){
                node.val=order[1];
                //remove(origin,origin[1]);
                node.left=new TreeNode(order[0]);
            }else{
                node.val=origin[index1];
                node.right=new TreeNode(origin[index2]);
            }

            return node;
        }
        if(origin.length==1){
            node.val=order[0];
            //remove(origin,origin[0]);
            return node;
        }

        if(origin.length==0){
            return null;
        }
        node.val=origin[0];
        int index=getIndex(order,origin[0]);



        if(index>0){
            int[] left=Arrays.copyOfRange(order,0,index);
            int[] oLeft=getOrigin(origin,left);
            TreeNode lNode=new TreeNode();
            node.left=lNode;
            bulid(left,lNode,oLeft);
        }
        if(index+1<origin.length){
            int[] right=Arrays.copyOfRange(order,index+1,order.length);
            int[] oRight=getOrigin(origin,right);
            TreeNode rNode=new TreeNode();
            node.right=rNode;
            bulid(right,rNode,oRight);
        }
        return node;
    }

    public static int  getIndex(int[] nums,int v){
        for (int i=0;i<nums.length;i++){
            if(v==nums[i]){
                return i;
            }
        }
        return -1;
    }
    public static void remove(int[] nums,int value){
        int[] reslut=new int[nums.length-1];
        for (int i=0,k=0;i<nums.length;i++){
            if(!(value==nums[i])){
                reslut[k]=nums[i];
                k++;
            }
        }
        nums=reslut;
    }
    public static int[] getOrigin(int[] origin,int[] part) {
        int[] result = new int[part.length];
        for(int i = 0,m=0; i < origin.length; i++){
            int value = origin[i];
            for (int k = 0; k < part.length ; k++){
                if(value==part[k]){
                    result[m]=value;
                    m++;
                }
            }
        }
        return result;
    }

}

题解学习优化

  • 查找左右子树分界线因为中序数组有序,可以使用二分查找
public class Solution {

    public TreeNode bstFromPreorder(int[] preorder) {
        int len = preorder.length;
        if (len == 0) {
            return null;
        }
        return dfs(preorder, 0, len - 1);
    }

    /**
     * 根据 preorder 的子区间 [left..right] 构建二叉树
     *
     * @param preorder
     * @param left
     * @param right
     * @return
     */
    private TreeNode dfs(int[] preorder, int left, int right) {
        if (left > right) {
            return null;
        }

        TreeNode root = new TreeNode(preorder[left]);
        if (left == right) {
            return root;
        }

        // 在区间 [left..right] 里找最后一个小于 preorder[left] 的下标
        // 注意这里设置区间的左边界为 left ,不能是 left + 1
        // 这是因为考虑到区间只有 2 个元素 [left, right] 的情况,第 1 个部分为空区间,第 2 部分只有一个元素 right
        int l = left;
        int r = right;

        while (l < r) {
            int mid = l + (r - l + 1) / 2;
            if (preorder[mid] < preorder[left]) {
                // 下一轮搜索区间是 [mid, r]
                l = mid;
            } else {
                // 下一轮搜索区间是 [l, mid - 1]
                r = mid - 1;
            }
        }
        
        TreeNode leftTree = dfs(preorder, left + 1, l);
        TreeNode rightTree = dfs(preorder, l + 1, right);
        root.left = leftTree;
        root.right = rightTree;
        return root;
    }
}

作者:LeetCode
链接:https://leetcode-cn.com/problems/construct-binary-search-tree-from-preorder-traversal/solution/jian-kong-er-cha-shu-by-leetcode/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

📖参考链接

题解链接:https://leetcode-cn.com/problems/construct-binary-search-tree-from-preorder-traversal/solution/jian-kong-er-cha-shu-by-leetcode/

posted @ 2022-03-25 00:03  bugMaker-java  阅读(102)  评论(0编辑  收藏  举报