题目链接:二叉树的层序遍历
题目描述:
给你二叉树的根节点 root ,返回其节点值的 层序遍历 。 (即逐层地,从左到右访问所有节点)。
解题思路:
层次遍历很容易就能想到可以使用队列来遍历,因为队列符合一层一层的出队列,而递归遍历则是按深度遍历,所以想用递归栈来模拟层次遍历则要多设置一个深度标志,来显示当前元素的层次来记录到结果集里。
代码实现:
递归法
class Solution {
public List<List<Integer>> res = new ArrayList<List<Integer>>();
public List<List<Integer>> levelOrder(TreeNode root) {
traversal(root,1);
return res;
}
public void traversal(TreeNode node,int deep){
if(node==null){
return;
}
if(res.size()<deep) {
res.add(new ArrayList<Integer>());
}
res.get(deep-1).add(node.val);
if(node.left!=null){
traversal(node.left,deep+1);
}
if(node.right!=null){
traversal(node.right,deep+1);
}
}
}
迭代法
class Solution {
public List<List<Integer>> levelOrder(TreeNode root) {
List<List<Integer>> res = new ArrayList<List<Integer>>();
Queue<TreeNode> queue = new LinkedList<>();
if(root==null){
return res;
}
queue.offer(root);
while(!queue.isEmpty()){
int len= queue.size();
List<Integer> List = new ArrayList<Integer>();
while(len>0){
TreeNode node = queue.poll();
List.add(node.val);
if(node.left!=null){
queue.offer(node.left);
}
if(node.right!=null){
queue.offer(node.right);
}
len--;
}
res.add(List);
}
return res;
}
}
题目链接:二叉树的层序遍历 II
题目描述:
给你二叉树的根节点 root ,返回其节点值 自底向上的层序遍历 。 (即按从叶子节点所在层到根节点所在的层,逐层从左向右遍历)
解题思路:
本题是逆向思维正常遍历后将结果反转即可,也能用头插法来实现无反转。
代码实现:
class Solution {
public List<List<Integer>> levelOrderBottom(TreeNode root) {
List<List<Integer>> res = new ArrayList<>();
Deque<TreeNode> que = new LinkedList<>();
if(root==null){
return res;
}
que.offer(root);
while(!que.isEmpty()){
List<Integer> temp = new ArrayList<>();
int len = que.size();
while(len>0){
TreeNode node = que.poll();
temp.add(node.val);
if(node.left!=null){
que.offer(node.left);
}
if(node.right!=null){
que.offer(node.right);
}
len--;
}
res.add(temp);
}
Collections.reverse(res);
return res;
}
}
优化无反转
class Solution {
public List<List<Integer>> levelOrderBottom(TreeNode root) {
List<List<Integer>> res = new ArrayList<>();
Deque<TreeNode> que = new LinkedList<>();
if(root==null){
return res;
}
que.offer(root);
while(!que.isEmpty()){
List<Integer> temp = new ArrayList<>();
int len = que.size();
while(len>0){
TreeNode node = que.poll();
temp.add(node.val);
if(node.left!=null){
que.offer(node.left);
}
if(node.right!=null){
que.offer(node.right);
}
len--;
}
res.addFirst(temp);
}
return res;
}
}
题目链接:
题目描述:
给定一个二叉树的 根节点 root,想象自己站在它的右侧,按照从顶部到底部的顺序,返回从右侧所能看到的节点值。
解题思路:
本题也比较简单,通过层次遍历,然后将每层最后一个元素加入结果集就可。
代码实现:
class Solution {
public List<Integer> rightSideView(TreeNode root) {
List<Integer> res = new ArrayList<>();
Queue<TreeNode> que = new LinkedList<>();
if(root==null){
return res;
}
que.offer(root);
while(!que.isEmpty()){
int len=que.size();
while(len>0){
TreeNode node = que.poll();
if(len==1){
res.add(node.val);
}
if(node.left!=null){
que.offer(node.left);
}
if(node.right!=null){
que.offer(node.right);
}
len--;
}
}
return res;
}
}
题目链接:二叉树的层平均值
题目描述:
给定一个非空二叉树的根节点 root , 以数组的形式返回每一层节点的平均值。与实际答案相差 10-5 以内的答案可以被接受。
解题思路:
本题也是简单题直接在每层遍历的时候算出和,每层遍历结束之后再计算平局值加入结果集。
代码实现:
class Solution {
public List<Double> averageOfLevels(TreeNode root) {
List<Double> res = new ArrayList<>();
Queue<TreeNode> que = new LinkedList<>();
if (root == null) {
return res;
}
que.offer(root);
while (!que.isEmpty()) {
int len = que.size();
double sum = 0.0;
for (int i = 0; i < len; i++) {
TreeNode node = que.poll();
sum += node.val;
if (node.left != null) {
que.offer(node.left);
}
if (node.right != null) {
que.offer(node.right);
}
}
res.add(sum / len);
}
return res;
}
}
题目链接:N 叉树的层序遍历
题目描述:
给定一个 N 叉树,返回其节点值的层序遍历。(即从左到右,逐层遍历)。
树的序列化输入是用层序遍历,每组子节点都由 null 值分隔(参见示例)。
解题思路:
此题和二叉树层序遍历只是多了个不确定是几个孩子,只需要将原先的二叉树遍历的孩子加入节点的部分更改一下即可。
代码实现:
class Solution {
public List<List<Integer>> levelOrder(Node root) {
List<List<Integer>> res = new ArrayList<List<Integer>>();
Queue<Node> que = new LinkedList<>();
if (root == null) {
return res;
}
que.offer(root);
while (!que.isEmpty()) {
List<Integer> temp = new ArrayList<>();
int len = que.size();
while (len > 0) {
Node node = que.poll();
temp.add(node.val);
if (node.children == null || node.children.size() == 0) {
len--;
continue;
}
for (Node i : node.children) {
if (i != null) {
que.offer(i);
}
}
len--;
}
res.add(temp);
}
return res;
}
}
题目链接:在每个树行中找最大值
题目描述:
给定一棵二叉树的根节点 root ,请找出该二叉树中每一层的最大值。
解题思路:本题也是简单题,只需在遍历每层的过程更新最大值就可。
代码实现:
class Solution {
public List<Integer> largestValues(TreeNode root) {
List<Integer> res = new ArrayList<>();
Queue<TreeNode> que = new LinkedList<>();
if (root == null) {
return res;
}
que.offer(root);
while (!que.isEmpty()) {
int max = Integer.MIN_VALUE;
int len = que.size();
for (int i = 0; i < len; i++) {
TreeNode node = que.poll();
if (node.val > max) {
max = node.val;
}
if (node.left != null) {
que.offer(node.left);
}
if (node.right != null) {
que.offer(node.right);
}
}
res.add(max);
}
return res;
}
}
题目链接:填充每个节点的下一个右侧节点指针
题目描述:
给定一个 完美二叉树 ,其所有叶子节点都在同一层,每个父节点都有两个子节点。二叉树定义如下:
struct Node {
int val;
Node *left;
Node *right;
Node *next;
}
填充它的每个 next 指针,让这个指针指向其下一个右侧节点。如果找不到下一个右侧节点,则将 next 指针设置为 NULL。
初始状态下,所有 next 指针都被设置为 NULL。
解题思路:
只需设置判断条件,判断是否在层尾,层尾指向null,其他则指向队头即可。
代码实现:
class Solution {
public Node connect(Node root) {
Queue<Node> que = new LinkedList<>();
if (root == null) {
return root;
}
que.offer(root);
while (!que.isEmpty()) {
int len = que.size();
for (int i = 0; i < len; i++) {
Node node = que.poll();
if(i==len-1){
node.next=null;
}else{
node.next=que.peek();
}
if (node.left != null) {
que.offer(node.left);
}
if (node.right != null) {
que.offer(node.right);
}
}
}
return root;
}
}
题目链接:填充每个节点的下一个右侧节点指针 II
题目描述:
给定一个二叉树:
struct Node {
int val;
Node *left;
Node *right;
Node *next;
}
填充它的每个 next 指针,让这个指针指向其下一个右侧节点。如果找不到下一个右侧节点,则将 next 指针设置为 NULL 。
初始状态下,所有 next 指针都被设置为 NULL 。
解题思路:
这道题目说是二叉树,但116题目说是完整二叉树,其实没有任何差别,一样的代码一样的逻辑一样的味道。
代码实现:
class Solution {
public Node connect(Node root) {
Queue<Node> que = new LinkedList<>();
if (root == null) {
return root;
}
que.offer(root);
while (!que.isEmpty()) {
int len = que.size();
for (int i = 0; i < len; i++) {
Node node = que.poll();
if (i == len - 1) {
node.next = null;
} else {
node.next = que.peek();
}
if (node.left != null) {
que.offer(node.left);
}
if (node.right != null) {
que.offer(node.right);
}
}
}
return root;
}
}
题目链接:二叉树的最大深度
题目描述:
给定一个二叉树 root ,返回其最大深度。
二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。
解题思路:
本题只需要使用一个层次记录,每层访问完加一。
代码实现:
class Solution {
public int maxDepth(TreeNode root) {
int res = 0;
Queue<TreeNode> queue = new LinkedList<>();
if(root==null){
return res;
}
queue.offer(root);
while(!queue.isEmpty()){
int len= queue.size();
while(len>0){
TreeNode node = queue.poll();
if(node.left!=null){
queue.offer(node.left);
}
if(node.right!=null){
queue.offer(node.right);
}
len--;
}
res++;
}
return res;
}
}
题目链接:二叉树的最小深度
题目描述:
给定一个二叉树,找出其最小深度。
最小深度是从根节点到最近叶子节点的最短路径上的节点数量。
说明:叶子节点是指没有子节点的节点。
解题思路:
此题只需要注意只有当左右孩子都为空的时候,才说明遍历的最低点了。如果其中一个孩子为空则不是最低点。
代码实现:
class Solution {
public int minDepth(TreeNode root) {
int res = 0;
Queue<TreeNode> queue = new LinkedList<>();
if (root == null) {
return res;
}
queue.offer(root);
while (!queue.isEmpty()) {
int len = queue.size();
res++;
while (len > 0) {
TreeNode node = queue.poll();
if (node.left != null) {
queue.offer(node.left);
}
if (node.right != null) {
queue.offer(node.right);
}
if(node.left==null&&node.right==null){
return res;
}
len--;
}
}
return res;
}
}
题目链接:翻转二叉树
题目描述:
给你一棵二叉树的根节点 root ,翻转这棵二叉树,并返回其根节点。
解题思路:此题只需要将每个节点的左右孩子互换即可。
代码实现:
递归法前
class Solution {
public TreeNode invertTree(TreeNode root) {
if(root==null){
return root;
}
swapChildren(root);
invertTree(root.left);
invertTree(root.right);
return root;
}
public void swapChildren(TreeNode root){
TreeNode node =root.left;
root.left=root.right;
root.right=node;
}
}
前序
swapChildren(root);
invertTree(root.left);
invertTree(root.right);
中序
//中序遍历处理完左子树和根后原先的右子树变到左子树所以在处理一遍左子树。
invertTree(root.left);
swapChildren(root);
invertTree(root.left);
后序
invertTree(root.left);
invertTree(root.right);
swapChildren(root);
层次遍历
class Solution {
public TreeNode invertTree(TreeNode root) {
if (root == null) {
return null;
}
ArrayDeque<TreeNode> deque = new ArrayDeque<>();
deque.offer(root);
while (!deque.isEmpty()) {
int len = deque.size();
while (len > 0) {
TreeNode node = deque.poll();
if (node.left != null){
deque.offer(node.left);
}
if (node.right != null){
deque.offer(node.right);
}
swap(node);
len--;
}
}
return root;
}
public void swap(TreeNode root) {
TreeNode temp = root.left;
root.left = root.right;
root.right = temp;
}
}
题目链接:对称二叉树
题目描述:
给你一个二叉树的根节点 root , 检查它是否轴对称。
解题思路:
此题可以使用双端队列,将节点的左右孩子对称加入队列中,然后不断比较队列的左右是否是对称的就可以了。
代码实现:
class Solution {
public boolean isSymmetric(TreeNode root) {
Deque<TreeNode> deque = new LinkedList<>();
deque.offerFirst(root.left);
deque.offerLast(root.right);
while (!deque.isEmpty()) {
TreeNode leftNode = deque.pollFirst();
TreeNode rightNode = deque.pollLast();
if (leftNode == null && rightNode == null) {
continue;
}
if (leftNode == null || rightNode == null || leftNode.val != rightNode.val) {
return false;
}
deque.offerFirst(leftNode.left);
deque.offerFirst(leftNode.right);
deque.offerLast(rightNode.right);
deque.offerLast(rightNode.left);
}
return true;
}
}