⭐北邮复试刷题105. 从前序与中序遍历序列构造二叉树__递归分治 (力扣每日一题)

本文主要是介绍⭐北邮复试刷题105. 从前序与中序遍历序列构造二叉树__递归分治 (力扣每日一题),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

105. 从前序与中序遍历序列构造二叉树

给定两个整数数组 preorder 和 inorder ,其中 preorder 是二叉树的先序遍历, inorder 是同一棵树的中序遍历,请构造二叉树并返回其根节点。

示例 1:
输入: preorder = [3,9,20,15,7], inorder = [9,3,15,20,7]
输出: [3,9,20,null,null,15,7]

示例 2:
输入: preorder = [-1], inorder = [-1]
输出: [-1]

提示:
1 <= preorder.length <= 3000
inorder.length == preorder.length
-3000 <= preorder[i], inorder[i] <= 3000
preorder 和 inorder 均 无重复 元素
inorder 均出现在 preorder
preorder 保证 为二叉树的前序遍历序列
inorder 保证 为二叉树的中序遍历序列

题解:

我们使用递归分治思想,因对于所给中序和前序,可通过前序序列确定第一个节点,再通过此节点在中序序列中的位置进而确定左右子树各自的中序序列,之后再通过其确定左右子树各自的前序序列,以此可进行递归处理;
同时注意某子树的中序序列长度和前序序列长度必为相等,可依据此性质确定递归时inorder数组和preorder数组下标起点终点该如何选择;
递归即对每个子树的中序和后序序列分别按照上述思想处理即可;

代码:

/*** 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 TreeNode buildTree(int[] preorder, int[] inorder) {
//         // 哈希表维护中序顺序,从而判断两元素之间方向关系
//         Map<Integer,Integer> map = new HashMap<>(); 
//         for(int i=0;i<inorder.length;i++){
//             map.put(inorder[i],i);
//         }//         // 建造节点依靠先序,中序作为验证判断,从而选择l或r方向延申
//         // 初始化第一个位置,因其为确定且唯一
//         TreeNode res = new TreeNode(preorder[0]);
//         TreeNode temp = res;//         // 其余元素需要加入中序判断
//         for(int i=1;i<preorder.length;i++){
//             int level = map.get(preorder[i]);
//             if(level > map.get(temp.val)){
//                 // 每次都叫node_new,但是分配区域不会回收
//                 // 只是名字被另一片区域剥夺,但因使用指针已经连接好,故不会混淆
//                 TreeNode node_new = new TreeNode(preorder[i]);
//                 temp.right = node_new;
//                 temp = temp.right;
//             }
//             else{
//                 // 同上 区别是若遍历到的节点在temp右方则必定temp加入此点后向right移动
//                 // 若在temp左方 需等待 因可能右方还有节点 
//                 // 当然也存在右方无节点情况 此时则需要判断下一节点是否仍为temp的left
//                 // 若是 则temp向left移动
//                 if(temp.left == null){
//                     TreeNode node_new = new TreeNode(preorder[i]);
//                     temp.left = node_new;
//                 }
//                 else{
//                     temp = temp.left;
//                     // 回溯未处理情况
//                     i--;
//                 } 
//             }
//         }//         return res;
//     }
// }// 递归法
class Solution {Map<Integer,Integer> map = new HashMap<>(); public TreeNode buildTree(int[] preorder, int[] inorder) {// 哈希表维护中序顺序,从而判断两元素之间方向关系for(int i=0;i<inorder.length;i++){map.put(inorder[i],i);}return ToBuildTree(preorder,inorder,0,preorder.length-1,0,inorder.length-1);}public TreeNode ToBuildTree(int[] preorder,int[] inorder,int preStart,int preEnd,int inStart,int inEnd){// 中序序列和先序序列长度必为相等,因此只需判断一个即可if(preStart > preEnd)return null;   // 对于递归设置一个终止条件即可// 根节点可立刻确定TreeNode res = new TreeNode(preorder[preStart]);// 此根在中序遍历中下标位置int inorder_pre = map.get(preorder[preStart]);// 运用每个子树的中序序列和其对应的前序序列长度相等的性质,可推断出左子树和右子树前序序列分界点int placeLeft = inorder_pre-1 - inStart;res.left = ToBuildTree(preorder,inorder,preStart+1,preStart+1+placeLeft,inStart,inorder_pre-1);int placeRight = inEnd - (inorder_pre+1);  res.right = ToBuildTree(preorder,inorder,preEnd-placeRight,preEnd,inorder_pre+1,inEnd);return res;}
}

结果:

在这里插入图片描述

这篇关于⭐北邮复试刷题105. 从前序与中序遍历序列构造二叉树__递归分治 (力扣每日一题)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/734670

相关文章

uva 10131 最长子序列

题意: 给大象的体重和智商,求体重按从大到小,智商从高到低的最长子序列,并输出路径。 代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <cmath>#include <stack>#include <vect

Codeforces Round #240 (Div. 2) E分治算法探究1

Codeforces Round #240 (Div. 2) E  http://codeforces.com/contest/415/problem/E 2^n个数,每次操作将其分成2^q份,对于每一份内部的数进行翻转(逆序),每次操作完后输出操作后新序列的逆序对数。 图一:  划分子问题。 图二: 分而治之,=>  合并 。 图三: 回溯:

POJ1631最长单调递增子序列

最长单调递增子序列 import java.io.BufferedReader;import java.io.InputStream;import java.io.InputStreamReader;import java.io.PrintWriter;import java.math.BigInteger;import java.util.StringTokenizer;publ

【每日一题】LeetCode 2181.合并零之间的节点(链表、模拟)

【每日一题】LeetCode 2181.合并零之间的节点(链表、模拟) 题目描述 给定一个链表,链表中的每个节点代表一个整数。链表中的整数由 0 分隔开,表示不同的区间。链表的开始和结束节点的值都为 0。任务是将每两个相邻的 0 之间的所有节点合并成一个节点,新节点的值为原区间内所有节点值的和。合并后,需要移除所有的 0,并返回修改后的链表头节点。 思路分析 初始化:创建一个虚拟头节点

leetcode105 从前序与中序遍历序列构造二叉树

根据一棵树的前序遍历与中序遍历构造二叉树。 注意: 你可以假设树中没有重复的元素。 例如,给出 前序遍历 preorder = [3,9,20,15,7]中序遍历 inorder = [9,3,15,20,7] 返回如下的二叉树: 3/ \9 20/ \15 7   class Solution {public TreeNode buildTree(int[] pr

每日一题|牛客竞赛|四舍五入|字符串+贪心+模拟

每日一题|四舍五入 四舍五入 心有猛虎,细嗅蔷薇。你好朋友,这里是锅巴的C\C++学习笔记,常言道,不积跬步无以至千里,希望有朝一日我们积累的滴水可以击穿顽石。 四舍五入 题目: 牛牛发明了一种新的四舍五入应用于整数,对个位四舍五入,规则如下 12345->12350 12399->12400 输入描述: 输入一个整数n(0<=n<=109 ) 输出描述: 输出一个整数

每日一练7:简写单词(含链接)

1.链接 简写单词_牛客题霸_牛客网 2.题目 3.代码1(错误经验) #include <iostream>#include <string>using namespace std;int main() {string s;string ret;int count = 0;while(cin >> s)for(auto a : s){if(count == 0){if( a <=

两数之和--力扣1

两数之和 题目思路C++代码 题目 思路 根据题目要求,元素不能重复且不需要排序,我们这里使用哈希表unordered_map。注意题目说了只对应一种答案。 所以我们在循环中,使用目标值减去当前循环的nums[i],得到差值,如果我们在map中能够找到这个差值,就说明存在两个整数的和为目标值。 如果没有找到,就将当前循环的nums[i]以及下标i放入map中,以便后续查

【每日刷题】Day113

【每日刷题】Day113 🥕个人主页:开敲🍉 🔥所属专栏:每日刷题🍍 🌼文章目录🌼 1. 91. 解码方法 - 力扣(LeetCode) 2. LCR 098. 不同路径 - 力扣(LeetCode) 3. 63. 不同路径 II - 力扣(LeetCode) 1. 91. 解码方法 - 力扣(LeetCode) //思路:动态规划。 cl

PHP实现二叉树遍历(非递归方式,栈模拟实现)

二叉树定义是这样的:一棵非空的二叉树由根结点及左、右子树这三个基本部分组成,根据节点的访问位置不同有三种遍历方式: ① NLR:前序遍历(PreorderTraversal亦称(先序遍历)) ——访问结点的操作发生在遍历其左右子树之前。 ② LNR:中序遍历(InorderTraversal) ——访问结点的操作发生在遍历其左右子树之中(间)。 ③ LRN:后序遍历(PostorderT