二叉树相关的面试题:
//数据结构
class TreeNode {
int value;
TreeNode left;
TreeNode right;
public TreeNode(int value) {
this.value = value;
}
}
1、输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
public class Solution {
public TreeNode reConstructBinaryTree(int [] pre,int [] in) {
if (pre.length == 0 || in.length == 0) {
return null;
}
TreeNode root = new TreeNode(pre[0]);
// 在中序中找到前序的根
for (int i = 0; i < in.length; i++) {
if (in[i] == pre[0]) {
// 左子树,注意 copyOfRange 函数,左闭右开
root.left = reConstructBinaryTree(Arrays.copyOfRange(pre, 1, i + 1), Arrays.copyOfRange(in, 0, i));
// 右子树,注意 copyOfRange 函数,左闭右开
root.right = reConstructBinaryTree(Arrays.copyOfRange(pre, i + 1, pre.length), Arrays.copyOfRange(in, i + 1, in.length));
break;
}
}
return root;
}
}
2、操作给定的二叉树,将其变换为源二叉树的镜像。
//非递归
public void Mirror(TreeNode root) {
if(root == null) return;
Queue<TreeNode> nodes = new LinkedList<>();
TreeNode curr, temp;
nodes.offer(root);
while(!nodes.isEmpty()){
int len = nodes.size();
for(int i = 0; i < len; i++){
curr = nodes.poll();
temp = curr.left;//交换左右节点,对角线
curr.left = curr.right;
curr.right = temp;
if(curr.left != null) nodes.offer(curr.left);
if(curr.right != null) nodes.offer(curr.right);
}
}
}
链接:https://www.nowcoder.com/questionTerminal/564f4c26aa584921bc75623e48ca3011?answerType=1&f=discussion
来源:牛客网
//递归
public void Mirror(TreeNode root){
if(root ==null)
return;
if(root.left ==null && root.right ==null)
return;
//交换左右子树
TreeNode tmp = root.left;
root.left = root.right;
root.right = tmp;
//递归将两给子树的左右子树镜像
if(root.left !=null)
Mirror(root.left);
if(root.right !=null)
Mirror(root.right);
}
3、从上往下打印出二叉树的每个节点,同层节点从左至右打印。
//BFS广度遍历--需要借助队列
public class Solution {
public ArrayList<Integer> PrintFromTopToBottom(TreeNode root) {
ArrayList<Integer> list = new ArrayList<Integer>();
Queue<TreeNode> queue = new LinkedList<TreeNode>();
if(root == null) return list;
queue.offer(root);
while(!queue.isEmpty()){
TreeNode node = queue.poll();
list.add(node.val);
if(node.left != null ){
queue.offer(node.left);
}
if(node.right != null){
queue.offer(node.right);
}
}
return list;
}
}
4、输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则输出Yes,否则输出No。假设输入的数组的任意两个数字都互不相同。
public static boolean isTreeAfter(int[] array, int start, int end) {
if (start >= end) return true;
int key = array[end];
int i;
//找到左右子数的分界点
for (i = start; start < end; start++)
if (array[start] > key)
break;
//在右子树中判断是否含有小于root的值,如果有返回false
for (int j = start; j < end; j++)
if (array[j] < key)
return false;
return isTreeAfter(array, 0, start - 1) && isTreeAfter(array, start, end - 1);
}
5、 输入一颗二叉树的根节点和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。(注意: 在返回值的list中,数组长度大的数组靠前)
public ArrayList<ArrayList<Integer>> FindPath(TreeNode root,int target) {
ArrayList<ArrayList<Integer>> res=new ArrayList<>();
ArrayList<Integer> cur=new ArrayList<>();
helper(root,target,cur,res);
Collections.sort(res, new Comparator<ArrayList<Integer>>() {
@Override
public int compare(ArrayList<Integer> o1, ArrayList<Integer> o2) {
if (o1.size()<o2.size()){
return 1;
}else return -1;
}
});
return res;
}
public void helper(TreeNode root,int target,ArrayList<Integer> cur,ArrayList<ArrayList<Integer>> res){
if (root==null) return;
int value=root.val;
cur.add(value);
if (target==value&&root.left==null&&root.right==null){
res.add(new ArrayList<>(cur));
}else {
helper(root.left,target-value,cur,res);
helper(root.right,target-value,cur,res);
}
cur.remove(cur.size()-1);
}
//方法二:添加排序--不太理解
public static ArrayList<ArrayList<Integer>> FindPath(TreeNode root, int target) {
ArrayList<ArrayList<Integer>> res = new ArrayList<>();
if (root == null)
return res;
if (root.left == null && root.right == null && root.value == target) {
ArrayList<Integer> path = new ArrayList<>();
path.add(root.value);
res.add(path);
return res;
}
ArrayList<ArrayList<Integer>> leftRes = FindPath(root.left, target - root.value);
ArrayList<ArrayList<Integer>> rightRes = FindPath(root.right, target - root.value);
addValToPath(leftRes, root.value);
addValToPath(rightRes, root.value);
// 保证数据长度长的排前面。用类似归并排序合并有序的思想,因为leftRes、rightRes已经有序
int leftPoint = 0, rightPoint = 0;
while (leftPoint != leftRes.size() && rightPoint != rightRes.size()) {
if (leftRes.get(leftPoint).size() > rightRes.get(rightPoint).size())
res.add(leftRes.get(leftPoint++));
else
res.add(rightRes.get(rightPoint++));
}
while (leftPoint < leftRes.size())
res.add(leftRes.get(leftPoint++));
while (rightPoint < rightRes.size())
res.add(rightRes.get(rightPoint++));
return res;
}
private static void addValToPath(ArrayList<ArrayList<Integer>> res, int val) {
for (ArrayList<Integer> path : res)
path.add(0, val);
}
6、二叉树的前序、中序、后序的非递归遍历,链接:https://blog.csdn.net/ChaunceyChen/article/details/88592559
7、输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。
解题思路:
1.核心是中序遍历的非递归算法。
2.修改当前遍历节点与前一遍历节点的指针指向。
import java.util.Stack;
public TreeNode ConvertBSTToBiList(TreeNode root) {
if(root==null)
return null;
Stack<TreeNode> stack = new Stack<TreeNode>();
TreeNode p = root;
TreeNode pre = null;// 用于保存中序遍历序列的上一节点
boolean isFirst = true;
while(p!=null||!stack.isEmpty()){
while(p!=null){
stack.push(p);
p = p.left;
}
p = stack.pop();
if(isFirst){
root = p;// 将中序遍历序列中的第一个节点记为root
pre = root;
isFirst = false;
}else{
pre.right = p;
p.left = pre;
pre = p;
}
p = p.right;
}
return root;
}