二叉树的层序遍历
二叉树的层序遍历,就是图论中的广度优先搜索在二叉树中的应用,需要借助队列来实现
Leetcode 102. 二叉树的层序遍历
题目链接:102. 二叉树的层序遍历
class Solution {
public List<List<Integer>> levelOrder(TreeNode root) {
List<List<Integer>> result = new ArrayList<>();
Deque<TreeNode> queue = new LinkedList<>();
if(root != null){
queue.add(root);
}
while(!queue.isEmpty()){
int size = queue.size();
List<Integer> list = new ArrayList<>();
while(size > 0){
TreeNode node = queue.poll();
list.add(node.val);
if(node.left != null){
queue.add(node.left);
}
if(node.right != null){
queue.add(node.right);
}
size--;
}
result.add(list);
}
return result;
}
}
Leetcode 107. 二叉树的层序遍历 II
题目链接:107. 二叉树的层序遍历 II
class Solution {
public List<List<Integer>> levelOrderBottom(TreeNode root) {
List<List<Integer>> result = new ArrayList<>();
Deque<TreeNode> queue = new LinkedList<>();
if(root == null){
return result;
}
queue.add(root);
while(!queue.isEmpty()){
int size = queue.size();
List<Integer> list = new ArrayList<>();
while(size > 0){
TreeNode node = queue.poll();
list.add(node.val);
if(node.left != null){
queue.add(node.left);
}
if(node.right != null){
queue.add(node.right);
}
size--;
}
result.add(list);
}
Collections.reverse(result);
return result;
}
}
优化解法, 最后不需要反转
class Solution {
public List<List<Integer>> levelOrderBottom(TreeNode root) {
LinkedList<List<Integer>> result = new LinkedList<>();
Deque<TreeNode> queue = new LinkedList<>();
if(root == null){
return result;
}
queue.add(root);
while(!queue.isEmpty()){
int size = queue.size();
List<Integer> list = new ArrayList<>();
while(size > 0){
TreeNode node = queue.poll();
list.add(node.val);
if(node.left != null){
queue.add(node.left);
}
if(node.right != null){
queue.add(node.right);
}
size--;
}
result.addFirst(list);
}
return result;
}
}
Leetcode 199. 二叉树的右视图
题目链接:199. 二叉树的右视图
class Solution {
public List<Integer> rightSideView(TreeNode root) {
List<Integer> result = new ArrayList<>();
Deque<TreeNode> queue = new LinkedList<>();
if(root == null){
return result;
}
queue.add(root);
while(!queue.isEmpty()){
int size = queue.size();
TreeNode node = null;
for(int i = 1; i <= size; i++){
node = queue.poll();
if(node.left != null){
queue.add(node.left);
}
if(node.right != null){
queue.add(node.right);
}
}
result.add(node.val);
}
return result;
}
}
Leetcode 637. 二叉树的层平均值
题目链接:637. 二叉树的层平均值
class Solution {
public List<Double> averageOfLevels(TreeNode root) {
List<Double> result = new ArrayList<>();
Deque<TreeNode> deque = new LinkedList<>();
deque.add(root);
while(!deque.isEmpty()){
int size = deque.size();
double sum = 0.0;
for(int i = 1; i <= size; i++){
TreeNode node = deque.poll();
sum += node.val;
if(node.left != null){
deque.add(node.left);
}
if(node.right != null){
deque.add(node.right);
}
}
result.add(sum / size);
}
return result;
}
}
Leetcode 429. N叉树的层序遍历
题目链接:429. N叉树的层序遍历
P.S. 被题目示例误导了,以为输入的是一长串掺杂 null 的元素集合
class Solution {
public List<List<Integer>> levelOrder(Node root) {
List<List<Integer>> result = new ArrayList<>();
Deque<Node> deque = new LinkedList<>();
if(root == null){
return result;
}
deque.add(root);
while(!deque.isEmpty()){
int size = deque.size();
List<Integer> list = new ArrayList<>();
for(int i = 1; i <= size; i++){
Node node = deque.poll();
list.add(node.val);
List<Node> children = node.children;
if(children == null || children.size() == 0){
continue;
}
for(Node child : children){
if(child != null){
deque.add(child);
}
}
}
result.add(list);
}
return result;
}
}
Leetcode 515. 在每个树行中找最大值
题目链接:515. 在每个树行中找最大值
class Solution {
public List<Integer> largestValues(TreeNode root) {
List<Integer> result = new ArrayList<>();
Deque<TreeNode> deque = new LinkedList<>();
if(root == null){
return result;
}
deque.add(root);
while(!deque.isEmpty()){
int size = deque.size();
int max = Integer.MIN_VALUE;
for(int i = 1; i <= size; i++){
TreeNode node = deque.poll();
// 或者:max = Math.max(max, node.val);
if(node.val > max){
max = node.val;
}
if(node.left != null){
deque.add(node.left);
}
if(node.right != null){
deque.add(node.right);
}
}
result.add(max);
}
return result;
}
}
Leetcode 116. 填充每个节点的下一个右侧节点指针
看题解,有用类似双指针的解法。但是我觉得我的这个解法简单一些。
class Solution {
public Node connect(Node root) {
if(root == null){
return root;
}
Deque<Node> deque = new LinkedList<>();
deque.add(root);
while(!deque.isEmpty()){
int size = deque.size();
Node nextNode = null;
for(int i = 1; i <= size; i++){
Node node = deque.poll();
node.next = nextNode;
if(node.right != null){
deque.add(node.right);
}
if(node.left != null){
deque.add(node.left);
}
nextNode = node;
}
}
return root;
}
}
Leetcode 117. 填充每个节点的下一个右侧节点指针II
上一题是完美二叉树,本题是普通二叉树,其实没有任何差别,解法一模一样
class Solution {
public Node connect(Node root) {
if(root == null){
return root;
}
Deque<Node> deque = new LinkedList<>();
deque.add(root);
while(!deque.isEmpty()){
int size = deque.size();
Node nextNode = null;
for(int i = 1; i <= size; i++){
Node node = deque.poll();
node.next = nextNode;
if(node.right != null){
deque.add(node.right);
}
if(node.left != null){
deque.add(node.left);
}
nextNode = node;
}
}
return root;
}
}
Leetcode 104. 二叉树的最大深度
题目链接:104. 二叉树的最大深度
class Solution {
public int maxDepth(TreeNode root) {
Deque<TreeNode> deque = new LinkedList<>();
if(root != null){
deque.add(root);
}
int depth = 0;
while(!deque.isEmpty()){
int size = deque.size();
depth++;
for(int i = 1; i <= size; i++){
TreeNode node = deque.poll();
if(node.left != null){
deque.add(node.left);
}
if(node.right != null){
deque.add(node.right);
}
}
}
return depth;
}
}
Leetcode 111. 二叉树的最小深度
题目链接:111. 二叉树的最小深度
class Solution {
public int minDepth(TreeNode root) {
Deque<TreeNode> deque = new LinkedList<>();
if(root != null){
deque.add(root);
}
int depth = 0;
while(!deque.isEmpty()){
int size = deque.size();
depth++;
for(int i = 1; i <= size; i++){
TreeNode node = deque.poll();
if(node.left == null && node.right == null){
return depth;
}
if(node.left != null){
deque.add(node.left);
}
if(node.right != null){
deque.add(node.right);
}
}
}
return depth;
}
}
Leetcode 226. 翻转二叉树
题目链接:226. 翻转二叉树
本题关键在于遍历顺序。针对二叉树的问题,解题之前一定要想清楚究竟是前中后序遍历,还是层序遍历。
class Solution {
public TreeNode invertTree(TreeNode root) {
if(root == null){
return root;
}
swap(root);
invertTree(root.left);
invertTree(root.right);
return root;
}
public void swap(TreeNode root) {
TreeNode tmp = root.left;
root.left = root.right;
root.right = tmp;
}
}
这道题使用层序遍历也可以。
Leetcode 101. 对称二叉树
题目链接:101. 对称二叉树
思路
第一想法是,层序遍历,用两个队列,分别从左到右和从右到左依次遍历,并对比node的value。或者两次递归,分别左中右遍历和右中左遍历,并对比node的value。但其实并不需要两个队列,也不是用中序遍历。
本题遍历只能是“后序遍历”,因为我们要通过递归函数的返回值来判断两个子树的内侧节点和外侧节点是否相等。正是因为要遍历两棵树而且要比较内侧和外侧节点,所以准确的来说是一个树的遍历顺序是左右中,一个树的遍历顺序是右左中。
或者把左右两个子树要比较的元素顺序放进一个容器,然后成对成对的取出来进行比较。
class Solution {
public boolean isSymmetric(TreeNode root) {
if(root == null){
return true;
}
return compare(root.left, root.right);
}
public boolean compare(TreeNode left, TreeNode right){
if(left == null && right != null){
return false;
}
if(right == null && left != null){
return false;
}
if(left == null && right == null){
return true;
}
if(left.val != right.val){
return false;
}
boolean outside = compare(left.left, right.right);
boolean inside = compare(left.right, right.left);
return outside && inside;
}
}
Leetcode 100. 相同的树
题目链接:100. 相同的树
class Solution {
public boolean isSameTree(TreeNode p, TreeNode q) {
return compare(p, q);
}
public boolean compare(TreeNode left, TreeNode right){
if(left == null && right != null){
return false;
}
if(right == null && left != null){
return false;
}
if(left == null && right == null){
return true;
}
if(left.val != right.val){
return false;
}
boolean leftCompare = compare(left.left, right.left);
boolean rightCompare = compare(left.right, right.right);
return leftCompare && rightCompare;
}
}
Leetcode 572. 另一棵树的子树
题目链接:572. 另一棵树的子树
class Solution {
public boolean isSubtree(TreeNode root, TreeNode subRoot) {
if(root == null){
return false;
}
return compare(root, subRoot) || isSubtree(root.left, subRoot) || isSubtree(root.right, subRoot);
}
public boolean compare(TreeNode left, TreeNode right){
if(left == null && right != null){
return false;
}
if(right == null && left != null){
return false;
}
if(left == null && right == null){
return true;
}
if(left.val != right.val){
return false;
}
boolean leftCompare = compare(left.left, right.left);
boolean rightCompare = compare(left.right, right.right);
return leftCompare && rightCompare;
}
}