前序遍历二叉搜索树
⭐前序遍历搜索二叉树
思路
将搜索二叉树前序遍历排序便得到该搜索二叉树的中序遍历,根据前序和中序遍历递归构造二叉树即可。
思路误区
- 排序后误将中序遍历的中间值作为根节点构造二叉树
- 递归到剩下3个节点可以继续递归
- 没次递归没有处理好下一次递归需要的前序和中序遍历数组。导致出错。
- 递归右子树时应该判断
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)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· .NET Core 中如何实现缓存的预热?
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 如何调用 DeepSeek 的自然语言处理 API 接口并集成到在线客服系统