目录
题目:
对给定的二叉树依次完成前序,中序,后序遍历,并输出遍历结果。
每行输入为一个二叉树,一维数组形式。其中-1表示Nil节点,例如:1,7,2,6,-1,4,8 构成的二叉树如下图所示:
结果以二维数组形式输出(前序,中序,后序遍历的结果),其中Nil节点不用输出。
输出示例:
代码编写:核心代码模式:
import java.util.*;
public class Solution {
/**
* 对给定的二叉树依次完成前序,中序,后序遍历,并输出遍历结果
* @param input int整型一维数组 -1表示Nil节点
* @return int整型ArrayList<ArrayList<>>
*/
public ArrayList<ArrayList<Integer>> binaryTreeScan (int[] input) {
// write code here
}
}
解答:
博主笨拙的想法——些许暴力
思路:
- 对于普通的二叉树的前序、中序、后序遍历,想必大家都是可以轻松拿捏的,所以博主从这里入手思考的,我只要利用这个数组,构造出一棵二叉树,就可以将这道题,轻松解答
- 现在,开始思考,如何讲该数组,构造出一棵二叉树
- 特殊情况,特殊考虑
input.length==0||input[0]==-1,直接返回空
- 利用队列,记录二叉树的节点,代码里面有更详细的解释:
//构建二叉树
public static TreeNode fun(int[] input) {
//特殊情况
if(input.length==0||input[0]==-1) {
return null;
}
//数组长度
int n = input.length;
Queue<TreeNode> queue = new LinkedList<>();
TreeNode root = new TreeNode(input[0]);
//将根节点先放进去
queue.add(root);
for(int i = 1;i<n;i++) {
//如果队列为空并且数组并没有走完,代表数组后面的值其实是无效值,这里不好理解的话,你可以自己随便画一个一组,看看,下面我也画了一组,可以看看(代码后面)
if(queue.isEmpty()) break;
TreeNode cur = queue.poll();
//左节点
if(input[i]==-1) {
cur.left=null;
} else {
cur.left = new TreeNode(input[i]);
queue.add(cur.left);
}
//右节点
i++;
if(i<n) {
if(input[i]==-1) {
cur.right=null;
} else {
cur.right = new TreeNode(input[i]);
queue.add(cur.right);
}
} else {
break;
}
}
return root;
}
代码中为什么说他是无效值?
二叉树都构造出来了,后面就很简单啦!不解释啦 ~
上代码:
import java.util.*;
public class Solution {
/**
* 对给定的二叉树依次完成前序,中序,后序遍历,并输出遍历结果
* @param input int整型一维数组 -1表示Nil节点
* @return int整型ArrayList<ArrayList<>>
*/
public ArrayList<ArrayList<Integer>> binaryTreeScan (int[] input) {
// write code here
ArrayList<ArrayList<Integer>> ret = new ArrayList<>();
//if(input.length==0||input[0]==-1) return ret;
TreeNode root = fun(input);
ret.add(preOrder(root));
ret.add(vinOrder(root));
ret.add(lastOrder(root));
return ret;
}
//构建二叉树
public TreeNode fun(int[] input) {
if(input.length==0||input[0]==-1) {
return null;
}
int n = input.length;
Queue<TreeNode> queue = new LinkedList<>();
TreeNode root = new TreeNode(input[0]);
queue.add(root);
for(int i = 1;i<n;i++) {
if(queue.isEmpty()) break;
TreeNode cur = queue.poll();
if(input[i]==-1) {
cur.left=null;
} else {
cur.left = new TreeNode(input[i]);
queue.add(cur.left);
}
i++;
if(i<n) {
if(input[i]==-1) {
cur.right=null;
} else {
cur.right = new TreeNode(input[i]);
queue.add(cur.right);
}
} else {
break;
}
}
return root;
}
//先序遍历
public ArrayList<Integer> preOrder(TreeNode root) {
ArrayList<Integer> ret = new ArrayList<>();
if(root == null) {
return ret;
}
ret.add(root.val);
ret.addAll(preOrder(root.left));
ret.addAll(preOrder(root.right));
return ret;
}
//中序遍历
public ArrayList<Integer> vinOrder(TreeNode root) {
ArrayList<Integer> ret = new ArrayList<>();
if(root == null) {
return ret;
}
ret.addAll(vinOrder(root.left));
ret.add(root.val);
ret.addAll(vinOrder(root.right));
return ret;
}
//后序遍历
public ArrayList<Integer> lastOrder(TreeNode root) {
ArrayList<Integer> ret = new ArrayList<>();
if(root == null) {
return ret;
}
ret.addAll(lastOrder(root.left));
ret.addAll(lastOrder(root.right));
ret.add(root.val);
return ret;
}
}
但是,这这这,他通过率只有百分之六十,博主绞尽脑汁,也没发现问题,呜呜呜呜~
于是乎,我就这样交卷了,交卷后,我去牛客上找到原题,将上述代码,提交了一遍,发现了问题所在,可真是为难到我了,测试不通过:
你发现问题了吗?
画个图来瞅瞅:
根据人家的预期输出结果,发现了思路应该是这样的:
哈哈哈,有没有被我误导了,真不好意思,哈哈哈哈哈哈!!!
因此,更改代码,在构建二叉树时,遇到-1值,也需要往队列里面放,只不过在前、中、后序遍历时,遇到-1,不记录而已~
上代码:
import java.util.*;
public class Solution {
/**
* 对给定的二叉树依次完成前序,中序,后序遍历,并输出遍历结果
* @param input int整型一维数组 -1表示Nil节点
* @return int整型ArrayList<ArrayList<>>
*/
public ArrayList<ArrayList<Integer>> binaryTreeScan (int[] input) {
// write code here
ArrayList<ArrayList<Integer>> ret = new ArrayList<>();
// if(input.length==0||input[0]==-1) return ret;
TreeNode root = fun(input);
ret.add(preOrder(root));
ret.add(vinOrder(root));
ret.add(lastOrder(root));
return ret;
}
//构建二叉树
public TreeNode fun(int[] input) {
if(input.length==0||input[0]==-1) {
return null;
}
int n = input.length;
Queue<TreeNode> queue = new LinkedList<>();
TreeNode root = new TreeNode(input[0]);
queue.add(root);
for(int i = 1;i<n;i++) {
if(queue.isEmpty()) break;
TreeNode cur = queue.poll();
cur.left = new TreeNode(input[i]);
queue.add(cur.left);
i++;
if(i<n) {
cur.right = new TreeNode(input[i]);
queue.add(cur.right);
} else {
break;
}
}
return root;
}
//先序遍历
public ArrayList<Integer> preOrder(TreeNode root) {
ArrayList<Integer> ret = new ArrayList<>();
if(root == null) {
return ret;
}
if(root.val!=-1)
ret.add(root.val);
ret.addAll(preOrder(root.left));
ret.addAll(preOrder(root.right));
return ret;
}
//中序遍历
public ArrayList<Integer> vinOrder(TreeNode root) {
ArrayList<Integer> ret = new ArrayList<>();
if(root == null) {
return ret;
}
ret.addAll(vinOrder(root.left));
if(root.val!=-1)
ret.add(root.val);
ret.addAll(vinOrder(root.right));
return ret;
}
//后序遍历
public ArrayList<Integer> lastOrder(TreeNode root) {
ArrayList<Integer> ret = new ArrayList<>();
if(root == null) {
return ret;
}
ret.addAll(lastOrder(root.left));
ret.addAll(lastOrder(root.right));
if(root.val!=-1)
ret.add(root.val);
return ret;
}
}
非常妙的方法:
如果根节点从0开始编号,对于任意一个节点i,其左孩子编号为2*i+1,右孩子编号为2*i+2,有了这个关系,就能够通过递归求得三种遍历序了
不理解?好的,普及一下二叉树的一些性质,很重要哦!
- 若规定根结点的层数为1,则一棵非空二叉树的第i层上最多有 (i>0)个结点
- 若规定只有根结点的二叉树的深度为1,则深度为K的二叉树的最大结点数是 (k>=0)
- 对任何一棵二叉树, 如果其叶结点个数为 n0, 度为2的非叶结点个数为 n2,则有n0=n2+1 具有n个结点的完全二叉树的深度k为上取整
- 对于具有n个结点的完全二叉树,如果按照从上至下从左至右的顺序对所有节点从0开始编号,则对于序号为i 的结点有:
不太理解?你只看文字当然不理解啦,动手画画!就知道了
好了,回到正题了,上代码咯!!!
import java.util.*;
public class Solution {
/**
* 对给定的二叉树依次完成前序,中序,后序遍历,并输出遍历结果
* @param input int整型一维数组 -1表示Nil节点
* @return int整型ArrayList<ArrayList<>>
*/
public ArrayList<ArrayList<Integer>> binaryTreeScan (int[] input) {
// write code here
ArrayList<ArrayList<Integer>> res = new ArrayList<>();
res.add(preOrder(input, 0));
res.add(inOrder(input, 0));
res.add(postOrder(input, 0));
return res;
}
//前序遍历
private ArrayList<Integer> preOrder(int[] nums, int root) {
ArrayList<Integer> ret = new ArrayList<>();
if(root >= nums.length){
return ret;
}
if(nums[root] != -1){
ret.add(nums[root]);
}
//位运算提高效率
ret.addAll(preOrder(nums, (root << 1)|1));
ret.addAll(preOrder(nums, (root << 1) + 2));
return ret;
}
//中序遍历
private ArrayList<Integer> inOrder(int[] nums, int root) {
ArrayList<Integer> ret = new ArrayList<>();
if(root >= nums.length){
return ret;
}
ret.addAll(inOrder(nums, (root << 1)|1));
if(nums[root] != -1){
ret.add(nums[root]);
}
ret.addAll(inOrder(nums, (root << 1) + 2));
return ret;
}
//后序遍历
private ArrayList<Integer> postOrder(int[] nums, int root) {
ArrayList<Integer> ret = new ArrayList<>();
if(root >= nums.length){
return ret;
}
ret.addAll(postOrder(nums, (root << 1)|1));
ret.addAll(postOrder(nums, (root << 1) + 2));
if(nums[root] != -1){
ret.add(nums[root]);
}
return ret;
}
}
好啦!今天就这儿咯!!!