PS:《剑指offer》是很多同学找工作都会参考的一本面试指南,同时也是一本算法指南(为什么它这么受欢迎,主要应该是其提供了一个循序渐进的优化解法,这点我觉得十分友好)。现在很多互联网的算法面试题基本上可以在这里找到影子,为了以后方便参考与回顾,现将书中例题用Java实现(第二版),欢迎各位同学一起交流进步。
GitHub: https://github.com/Uplpw/SwordOffer。
剑指offer完整题目链接: https://blog.csdn.net/qq_41866626/article/details/120415258
1 题目描述
题目1:
从上到下打印出二叉树的每个节点,同一层的节点按照从左到右的顺序打印。
题目2:
从上到下按层打印二叉树,同一层的节点按从左到右的顺序打印,每一层打印到一行。
题目3:
请实现一个函数按照之字形顺序打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右到左的顺序打印,第三行再按照从左到右的顺序打印,其他行以此类推。
leetcode链接: 从上到下打印二叉树-I(以下代码已测试,提交通过)
leetcode链接: 从上到下打印二叉树-II(以下代码已测试,提交通过)
leetcode链接: 从上到下打印二叉树-III(以下代码已测试,提交通过)
2 测试用例
一般是考虑功能用例,特殊(边缘)用例或者是反例,无效测试用例这三种情况。甚至可以从测试用例寻找一些规律解决问题,同时也可以让我们的程序更加完整鲁棒。
(1)功能用例:完全与非完全二叉树。
(2)边缘用例:只有一个节点,只有左节点,只有右节点。
(3)无效用例:树为空。
3 思路
分析:
很显然考查二叉树的层序遍历(关于树的遍历可以参考:二叉树遍历总结),可以借助List存储相关元素进行返回
题目1:
因为没有什么变化,直接使用层序遍历即可。
题目2:
由于逐行输出,所以需要对层序遍历做出一些改变。具体就是:由于使用队列存储每一行的节点,所以每次在while循环中利用for循环一次性输出即可,具体实现见代码。
题目3:
由于是之字形输出,所以在题目2解法的基础上设置一个变量记录当前行的奇偶,然后判断是否将元素对称互换即可。
4 代码
树的结构:
public class TreeNode {
public int val;
public TreeNode left;
public TreeNode right;
public TreeNode(int val) {
this.val = val;
this.left = null;
this.right = null;
}
}
题目1:
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Queue;
public class PrintTreeFromTopToBottom1 {
public int[] levelOrder(TreeNode root) {
if (root == null) {
return new int[0];
}
List<Integer> list = new ArrayList<Integer>();
Queue queue = new LinkedList<>();
queue.add(root);
TreeNode temp = null;
while (!queue.isEmpty()) {
temp = (TreeNode) queue.poll();
list.add(temp.val);
if (temp.left != null) {
queue.offer(temp.left);
}
if (temp.right != null) {
queue.offer(temp.right);
}
}
int[] array = new int[list.size()];
for (int i = 0; i < list.size(); i++) {
array[i] = list.get(i);
}
return array;
}
}
题目2:
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
public class PrintTreeFromTopToBottom2 {
public List<List<Integer>> levelOrder(TreeNode root) {
List<List<Integer>> list = new ArrayList();
if (root == null) {
return list;
}
Queue queue = new LinkedList();
queue.add(root);
while (!queue.isEmpty()) {
List<Integer> tempList = new ArrayList<>();
int size = queue.size();
for (int i = size - 1; i >= 0; i--) {
TreeNode temp = (TreeNode) queue.poll();
tempList.add(temp.val);
if (temp.left != null) {
queue.offer(temp.left);
}
if (temp.right != null) {
queue.offer(temp.right);
}
}
list.add(tempList);
}
return list;
}
}
题目3:
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
public class PrintTreeFromTopToBottom3 {
public List<List<Integer>> levelOrder(TreeNode root) {
List<List<Integer>> list = new ArrayList();
if (root == null) {
return list;
}
Queue queue = new LinkedList();
queue.add(root);
int count = 0;
while (!queue.isEmpty()) {
count++;
List<Integer> tempList = new ArrayList<>();
int size = queue.size();
for (int i = size - 1; i >= 0; i--) {
TreeNode temp = (TreeNode) queue.poll();
tempList.add(temp.val);
if (temp.left != null) {
queue.offer(temp.left);
}
if (temp.right != null) {
queue.offer(temp.right);
}
}
// 根据规律将存储的元素对称互换即可
if ((count & 1) == 0) {
int length = tempList.size();
for (int i = 0; i < length / 2; i++) {
int temp = tempList.get(i);
tempList.set(i, tempList.get(length - 1 - i));
tempList.set(length - 1 - i, temp);
}
}
list.add(tempList);
}
return list;
}
}
参考
在解决本书例题时,参考了一些大佬的题解,比如leetcode上的官方、K神,以及其他的博客,在之后的每个例题详解后都会给出参考的思路或者代码链接,同学们都可以点进去看看!
本文如有什么不足或不对的地方,欢迎大家批评指正,最后希望能和大家一起交流进步、拿到心仪的 offer !!!