二叉树进阶面试题

2021/8/21 19:42:39 浏览：

1. 二叉树的构建及遍历。

2. 二叉树的分层遍历 。

3. 给定一个二叉树, 找到该树中两个指定节点的最近公共祖先 。

4. 二叉树搜索树转换成排序双向链表。

5. 根据一棵树的前序遍历与中序遍历构造二叉树。

6. 根据一棵树的中序遍历与后序遍历构造二叉树

7. 二叉树创建字符串。

``````package tree;

import sun.font.CreatedFontTracker;

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

class TreeNode {
public char val;
public TreeNode left;
public TreeNode right;

public TreeNode(char val) {
this.val = val;
}
}

public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
while (scanner.hasNext()) {
String str = scanner.nextLine();
TreeNode root = build(str);
inOrder(root);
System.out.println();
}
System.out.println("下面是build1:");
TreeNode t = build1();
inOrder(t);
System.out.println("--------");
Solution s = new Solution();
System.out.println(s.levelOrder(t).toString());
}

public static int index = 0;

public static TreeNode build(String str) {
index = 0;

return creatTreePrevOrede(str);
}

private static TreeNode creatTreePrevOrede(String str) {
char c = str.charAt(index);
if (c == '#') {
return null;
}
TreeNode treeNode = new TreeNode(c);
index++;
treeNode.left = creatTreePrevOrede(str);
index++;
treeNode.right = creatTreePrevOrede(str);
return treeNode;
}

public static void inOrder(TreeNode root) {
if (root == null) {
return;
}
inOrder(root.left);
System.out.print(root.val);
inOrder(root.right);
}
//给你一个二叉树，请你返回其按 层序遍历 得到的节点值。 （即逐层地，从左到右访问所有节点）。

public static TreeNode build1() {
TreeNode a = new TreeNode('A');
TreeNode b = new TreeNode('B');
TreeNode c = new TreeNode('C');
TreeNode d = new TreeNode('D');
TreeNode e = new TreeNode('E');
TreeNode f = new TreeNode('F');
TreeNode g = new TreeNode('G');
a.left = b;
a.right = null;
b.left = c;
b.right = d;
d.left = e;
d.right = f;
e.right = g;
return a;
}
}

class Solution {
public List<List<Character>> levelOrder(TreeNode root) {
if (root == null) {
return lists;
}
int lever = 0;
return heper(root, 0);
}

public List<List<Character>> lists = new ArrayList<>();

public List<List<Character>> heper(TreeNode root, int lever) {

if (lever == lists.size()) {
}
if (root.left != null) {
heper(root.left, lever + 1);
}
if (root.right != null) {
heper(root.right, lever + 1);
}
return lists;
}

@Override
public String toString() {
return "{" +
lists +
'}';
}
}

/*
* 给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。

* 满足 x 是 p、q 的祖先且 x 的深度尽可能大（一个节点也可以是它自己的祖先）。”
*/
class Solution1 {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if (root == null) {
return null;
}
heper(root, p, q);
return lca;
}

private TreeNode lca = null;

public boolean heper(TreeNode root, TreeNode p, TreeNode q) {
if (root == null) {
return false;
}
int left = heper(root.left, p, q) ? 1 : 0;
int right = heper(root.right, p, q) ? 1 : 0;
int mid = (root == p || root == q) ? 1 : 0;
if (mid + left + right == 2) {
lca = root;
}

return (mid + left + right) > 0;
}

//方法二

public TreeNode contains(TreeNode root, TreeNode p, TreeNode q) {
if (root == null) {
return null;
}
heper2(root, p, q);
return lca2;
}

private TreeNode lca2 = null;
public int index = 0;

private int heper2(TreeNode root, TreeNode p, TreeNode q) {
if (root == null) {
return 0;
}

int left = heper2(root.left, p, q);
if (root.left == q || root.left == p) {
index++;
}
int right = heper2(root.right, p, q);
if (root.right == q || root.right == p) {
index++;
}
if (root == q || root == p) {
index++;
}
if (index == 2) {
lca2 = root;
return 2;
}
return index;

}

/*
1.要求不能创建任何新的结点，只能调整树中结点指针的指向。当转化完成以后，树中节点的左指针需要指向前驱，树中节点的右指针需要指向后继
2.返回链表中的第一个节点的指针
3.函数返回的TreeNode，有左右指针，其实可以看成一个双向链表的数据结构
4.你不用输出或者处理，示例中输出里面的英文，比如"From left to right are:"这样的，程序会根据你的返回值自动打印输出
*/
public TreeNode Convert(TreeNode pRootOfTree) {
if (pRootOfTree == null) {
return null;
}
return heper3(pRootOfTree);
}

private TreeNode heper3(TreeNode pRootOfTree) {
if (pRootOfTree == null) {
return null;
}
if (pRootOfTree.left == null && pRootOfTree.right == null) {
return pRootOfTree;
}

TreeNode left = heper3(pRootOfTree.left);
TreeNode leftTail = left;
while (leftTail != null && leftTail.right != null) {
leftTail = leftTail.right;
}
if (left != null) {
leftTail.right = left;
left.left = leftTail;
}
TreeNode right = heper3(pRootOfTree.right);
if (right != null) {
pRootOfTree.right = right;
right.left = pRootOfTree;
}
if (left != null) {
return left;
}
return pRootOfTree;
}

/*你需要采用前序遍历的方式，将一个二叉树转换成一个由括号和整数组成的字符串。

*/
public String tree2str(TreeNode root) {
if (root == null) {
return "";
}
heper4(root);
sb.deleteCharAt(0);
sb.deleteCharAt(sb.length() - 1);
return sb.toString();
}

private StringBuilder sb = new StringBuilder();

public void heper4(TreeNode root) {
if (root == null) {
return;
}
sb.append("(");
sb.append(root.val);
heper4(root.left);
if (root.left == null && root.right != null) {
sb.append("()");
}
heper4(root.right);
sb.append(")");
}

/*给定一棵树的前序遍历 preorder 与中序遍历  inorder。请构造二叉树并返回其根节点。
*/
//public int index;
public TreeNode buildTree(char[] preorder, char[] inorder) {
index = 0;
return buildTreeHeper(preorder, inorder, 0, inorder.length);
}

private TreeNode buildTreeHeper(char[] preorder, char[] inorder, int left, int right) {
if (left >= right) {
return null;
}
if (index >=inorder.length) {
return null;
}
TreeNode root = new TreeNode(preorder[index]);
index++;
char tofind = root.val;
int pos=find(inorder, left, right, tofind);
root.left=buildTreeHeper(preorder,inorder,left,pos);
root.right=buildTreeHeper(preorder,inorder,pos+1,right);
return root;
}

private int find(char[] inorder, int left, int right, char tofind) {
for (int i = left; i <right ; i++) {
if(inorder[i]==tofind){
return i;
}
}
return -1;
}

}

``````

前中后序的非递归实现：

1.前序遍历 void preOrderTraversal(Node root);

2.中序遍历 void inOrderTraversal(Node root);

3. 后序遍历 void postOrderTraversal(Node root);

``````package tree;

import java.util.Collection;
import java.util.List;
import java.util.Stack;

class TreeNode1 {
public int val;
public TreeNode1 left;
public TreeNode1 right;

public TreeNode1(int val) {
this.val = val;
}
}

public static void main(String[] args) {
TreeNode1 t = buildTree();
preOrder(t);
System.out.println();
inOrder(t);
System.out.println();

postOrderTraversal(t);
}

//非递归完成二叉树前序遍历
//需要一个辅助栈
public static void preOrder(TreeNode1 root) {
Stack<TreeNode1> s = new Stack<>();
if (root == null) {
return;
}
s.push(root);
while (!s.isEmpty()) {
TreeNode1 t = s.pop();
System.out.print(t.val);
if (t.right != null) {
s.push(t.right);
}
if (t.left != null) {
s.push(t.left);
}
}
}

//非递归完成二叉树中序遍历
//需要一个辅助栈
public static void inOrder(TreeNode1 root) {
if (root == null) {
return;
}
Stack<TreeNode1> s = new Stack<>();
TreeNode1 cur = root;
while (true) {
while (cur != null) {
s.push(cur);
cur = cur.left;
}
if (s.isEmpty()) {
break;
}
TreeNode1 tmp = s.pop();
System.out.print(tmp.val);

cur = tmp.right;
}
}

//非递归完成二叉树后序遍历
//需要一个辅助栈
public static void postOrderTraversal(TreeNode1 root) {
if (root == null) {
return;
}
Stack<TreeNode1> s = new Stack<>();

TreeNode1 tmp = root;
TreeNode1 prv = null;

while (true) {
while (tmp != null) {
s.push(tmp);
tmp = tmp.left;
}
if (s.isEmpty()) {
break;
}
TreeNode1 top = s.peek();
if (top.right == null || top.right.val == prv.val) {
System.out.print(top.val);
s.pop();
prv = top;
} else {
tmp = top.right;
}
}

}

public static TreeNode1 buildTree() {
TreeNode1 a = new TreeNode1(1);
TreeNode1 b = new TreeNode1(2);
TreeNode1 c = new TreeNode1(3);
TreeNode1 d = new TreeNode1(4);
TreeNode1 e = new TreeNode1(5);
TreeNode1 f = new TreeNode1(6);
TreeNode1 g = new TreeNode1(7);
a.left = b;
a.right = c;
b.left = d;
b.right = e;
c.left = f;
c.right = g;
return a;

}
}
``````