数据结构每日一练【二叉树的进阶面试题】
1.二叉树遍历
题目:有一先序遍历字符串: ABC##DE#G##F### 其中“#”表示的是空格,空格字符代表空树。建立起此二叉树以后,再对二叉树进行中序遍历,输出遍历结果。
代码:
import java.util.*;
//创建一个结点类型
class TreeNode{
public char val;//结点的值
public TreeNode left;//结点的左树
public TreeNode right;//结点的右树
public TreeNode(char val){
this.val = val;
}
}
public class Main{
//创建二叉树
public static int i=0;//定义一个变量,来定位str的字符
public static TreeNode creatTree(String str){
TreeNode root = null;
if(str.charAt(i) != '#'){
root = new TreeNode(str.charAt(i));//只要定位到的字符不是#,就需要new一个新的结点
i++;//定位下一个字符
root.left = creatTree(str);//创建左树
root.right = creatTree(str);//创建右树
}else{
i++;//遇见#,不做操作,直接i++,定位下一个字符
}
return root;
}
//中序遍历二叉树
public static void inOrderTracersal(TreeNode root){
if(root == null){
return ;
}
inOrderTracersal(root.left);
System.out.print(root.val+" ");
inOrderTracersal(root.right);
}
public static void main(String[] args){
Scanner scan = new Scanner(System.in);
while(scan.hasNextLine()){
String str = scan.nextLine();
TreeNode root = creatTree(str);
inOrderTracersal(root);
}
}
}
运行结果:
2.二叉树的最近公共祖先
题目:给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。
分析:主要分如下几种情况
- 从左树,和右树都没有找到p和q,返回null
- 左树没有找到p和q,右树返回p或者q,那么p和q的公共祖先就是右树返回的这个值
- 右树没有找到p和q,左树返回p或者q,那么p和q的公共祖先就是左树返回的这个值
- 左边返回q,右边返回p,他们的公共祖先是root(根节点)
代码:
class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if(root == null){
return null;
}
if(root == p || root == q ){
return root;
}
TreeNode left = lowestCommonAncestor(root.left,p,q);
TreeNode right = lowestCommonAncestor(root.right,p,q);
if(left != null && right == null){
return left;
}
if(left == null && right != null){
return right;
}
if(left != null && right != null){
return root;
}
return null;
}
}
运行结果:
3.二叉排序树
题目:输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表
分析:
中序遍历,会在合适的时机,获取合适的节点,然后进行修改每个节点的指向
代码:
public class Solution {
TreeNode prev = null;
public void ConvertChild(TreeNode pCur) {
if(pCur == null){return ;}
ConvertChild(pCur.left);
pCur.left = prev;
if(prev != null){
prev.right = pCur;
}
prev = pCur;
ConvertChild(pCur.right);
}
public TreeNode Convert(TreeNode pRootOfTree) {
if(pRootOfTree == null){return null;}
ConvertChild(pRootOfTree);
TreeNode head = pRootOfTree;
while(head.left != null){
head = head.left;
}
return head;
}
}
4.从前序与中序遍历序列构造二叉树
题目:给定一棵树的前序遍历 preorder 与中序遍历 inorder。请构造二叉树并返回其根节点。
Input: preorder = [3,9,20,15,7], inorder = [9,3,15,20,7]
Output: [3,9,20,null,null,15,7]
代码:
class Solution {
public int pi=0;
public TreeNode buildTreeChild(int[] preorder, int[] inorder,int begin,int end) {
if(begin > end){
return null;
}
TreeNode root = new TreeNode(preorder[pi]);
int ri = findIndex(inorder,begin,end,preorder[pi]);//找到了根节点在中序序列里面的下标位置
pi++;
root.left = buildTreeChild(preorder,inorder,begin,ri-1);
root.right = buildTreeChild(preorder,inorder,ri+1,end);
return root;
}
// 在中序遍历序列里面找,从前序序列里面传来的字符的下标
public int findIndex(int[] inorder,int begin,int end,int key){
for(int i=0;i<=end;i++){
if(inorder[i] == key){
return i;
}
}
return -1;
}
public TreeNode buildTree(int[] preorder, int[] inorder) {
return buildTreeChild(preorder,inorder,0,inorder.length-1);
}
}
5.二叉树创建字符串
题目:空节点则用一对空括号 “()” 表示。而且你需要省略所有不影响字符串与原始二叉树之间的一对一映射关系的空括号对。
输入: 二叉树: [1,2,3,4]
1
/
2 3
/
4
输出: “1(2(4))(3)”
解释: 原本将是“1(2(4)())(3())”,在你省略所有不必要的空括号对之后,它将是“1(2(4))(3)”。
代码:
class Solution {
public void tree2strChild(TreeNode t,StringBuilder sb) {
if(t ==null){
return;
}
sb.append(t.val);
if(t.left == null){
if(t.right == null){
return;
}else{
sb.append("()");
}
}else{
sb.append("(");
tree2strChild(t.left,sb);
sb.append(")");
}
if(t.right == null){
return;
}else{
sb.append("(");
tree2strChild(t.right,sb);
sb.append(")");
}
}
public String tree2str(TreeNode root) {
if(root == null){
return null;
}
StringBuilder sb = new StringBuilder();
tree2strChild(root,sb);
return sb.toString();
}
}
注:以上题目相应练习网址:
1.二叉树的构建及遍历
2.两个指定节点的最近公共祖先
3.二叉树搜索树转换成排序双向链表
4.前序遍历与中序遍历构造二叉树
5.二叉树创建字符串