二叉树的操作算法是笔试面试中较为常见的题目。
本文将着重介绍平时面试中常见的关于二叉树的应用题目,马上要进行秋招了。希望对你们有帮助 _
给你二叉树的根节点 root ,请你采用前序遍历的方式,将二叉树转化为一个由括号和整数组成的字符串,返回构造出的字符串。
空节点使用一对空括号对 “()” 表示,转化后需要省略所有不影响字符串与原始二叉树之间的一对一映射关系的空括号对。
/**
* 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 String tree2str(TreeNode root) {
}
}
我们可以使用递归的方法得到二叉树的前序遍历,并在递归时加上额外的括号。
会有以下 4种情况:
如果当前节点有两个孩子,那我们在递归时,需要在两个孩子的结果外都加上一层括号;
如果当前节点只有左孩子,那我们在递归时,只需要在左孩子的结果外加上一层括号,而不需要给右孩子加上任何括号;
如果当前节点只有右孩子,那我们在递归时,需要先加上一层空的括号 ‘()’\text{`()'}‘()’ 表示左孩子为空,再对右孩子进行递归,并在结果外加上一层括号。
那我们具体应该怎么做呢?
做法如下:
/**
* 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 String tree2str(TreeNode root) {
if(root == null) {
return null;
}
StringBuilder stringBuilder = new StringBuilder();
tree2strChild(root,stringBuilder);
return stringBuilder.toString();
}
public void tree2strChild(TreeNode t,StringBuilder stringBuilder) {
if(t == null) {
return;
}
stringBuilder.append(t.val);
if(t.left != null) {
stringBuilder.append("(");
tree2strChild(t.left,stringBuilder);
stringBuilder.append(")");
}else {
//左边为空了
if(t.right != null) {
//右边不为空
stringBuilder.append("()");
}else {
//右边为空
return ;
}
}
if(t.right == null) {
return;
}else {
stringBuilder.append("(");
tree2strChild(t.right,stringBuilder);
stringBuilder.append(")");
}
}
}
给你一棵树让你判断是不是完全二叉树
其实这道题与博主前面所讲的层序遍历类似
这时候队列元素为
这时候我可以将队列进行出队,元素全部为null,则为完全二叉树
boolean isCompleteTree(TreeNode root){
if(root == null) {
return true;
}
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
while (!queue.isEmpty()) {
TreeNode cur = queue.poll();
if(cur != null) {
queue.offer(cur.left);
queue.offer(cur.right);
}else {
break;
}
}
while (!queue.isEmpty()) {
TreeNode tmp = queue.poll();
if(tmp != null) {
return false;
}
}
return true;
}
给你二叉树的根节点 root ,返回它节点值的 前序 遍历。
/**
* 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 List<Integer> preorderTraversal(TreeNode root) {
}
}
我们创建一个栈来实现迭代的前序遍历
- 首先我们对cur进行判断,若不为null,
- 则将cur入栈,并将该元素存储在顺序表list里
- 然后遍历cur的左子树
将上述操作放入一个循环里,循环条件就为cur是否为null;
当cur为null时,我们就将栈中元素进行出栈赋给变量top
并用cur访问top的右子树
上面的操作我们再放入一个外循环里,条件为cur不为null或者栈不为空
/**
* 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 List<Integer> preorderTraversal(TreeNode root) {
List<Integer> list = new ArrayList<>();
if(root == null) {
return list;
}
TreeNode cur = root;
Deque<TreeNode> stack = new ArrayDeque<>();
while (cur != null || !stack.isEmpty()) {
while (cur != null) {
stack.push(cur);
list.add(cur.val);
cur = cur.left;
}
TreeNode top = stack.pop();
cur = top.right;
}
return list;
}
}
给定一个二叉树的根节点 root ,返回 它的 中序 遍历 。
/**
* 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 List<Integer> inorderTraversal(TreeNode root) {
}
}
与前序遍历步骤大致相同
不同的是中序遍历需要先在顺序表内存储左节点
也就是说我们需要先将该节点的左节点全部入栈后,然后再出栈到顺序表内
接下来访问右子树
/**
* 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 List<Integer> inorderTraversal(TreeNode root) {
List<Integer> list = new ArrayList<>();
if(root == null) {
return list;
}
TreeNode cur = root;
Deque<TreeNode> stack = new ArrayDeque<>();
while (cur != null || !stack.isEmpty()) {
while (cur != null) {
stack.push(cur);
cur = cur.left;
}
TreeNode top = stack.pop();
list.add(top.val);
cur = top.right;
}
return list;
}
}
给你一棵二叉树的根节点 root ,返回其节点值的 后序遍历 。
/**
* 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 List<Integer> postorderTraversal(TreeNode root) {
}
}
入栈思路与前序遍历和中序遍历思路相同
只是出栈不同
当然现在的思路还有一个问题,我们可能重复遍历top的右子树,最终程序崩溃
所以我们这里加一个变量pero进行判断,若相等则不再遍历该右节点
/**
* 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 List<Integer> postorderTraversal(TreeNode root) {
List<Integer> list = new ArrayList<>();
if(root == null) {
return list;
}
TreeNode cur = root;
TreeNode prev = null;
Deque<TreeNode> stack = new ArrayDeque<>();
while (cur != null || !stack.isEmpty()) {
while (cur != null) {
stack.push(cur);
cur = cur.left;
}
TreeNode top = stack.peek();
if(top.right == null || top.right == prev) {
list.add(top.val);
stack.pop();
prev = top;
}else {
cur = top.right;
}
}
return list;
}
}
关于《【数据结构】 二叉树面试题讲解->叁》就讲解到这儿,感谢大家的支持,欢迎各位留言交流以及批评指正,如果文章对您有帮助或者觉得作者写的还不错可以点一下关注,点赞,收藏支持一下!