层序遍历
题目链接:102. 二叉树的层序遍历 - 力扣(LeetCode)
思路:递归相当于直接操作resList数组,需要传递当前层数,将resList最新的出来,加入当前root的值,再递归传入左孩子和右孩子。
迭代需要队列,且两个while,外层while是queue不为空,内层while是queue的大小,提前获取queue的长度,然后进入内层循环,弹出队列元素将值加入到resList,然后再将该元素的左右孩子入队。
class Solution {
public List<List<Integer>> resList = new ArrayList<List<Integer>>();
public List<List<Integer>> levelOrder(TreeNode root) {
//levelTraver01(root,0);
levelTraver02(root);
return resList;
}
//DFS--递归遍历
//deep是层数
public void levelTraver01(TreeNode root,Integer deep){
if(root == null) return;
deep++;
//reslist是双层列表例:[[1],[2,3]],其外层的大小等于当前层数-1
if(resList.size() < deep){
List<Integer> item = new ArrayList<Integer>();
resList.add(item);//加入空列表
}
resList.get(deep-1).add(root.val);
levelTraver01(root.left,deep);
levelTraver01(root.right,deep);
}
//DFS--迭代方式--借助队列
public void levelTraver02(TreeNode node){
if(node == null) return;
Queue<TreeNode> queue = new LinkedList<TreeNode>();
queue.offer(node);
while(!queue.isEmpty()){
List<Integer> itemList = new ArrayList<Integer>();
int len = queue.size();
while(len > 0){
TreeNode tmpNode = queue.poll();
itemList.add(tmpNode.val);
if(tmpNode.left != null) queue.offer(tmpNode.left);
if(tmpNode.right != null) queue.offer(tmpNode.right);
len--;
}
resList.add(itemList);
}
}
}
2题目链接:107. 二叉树的层序遍历 II - 力扣(LeetCode)
思路:反转外层列表
class Solution {
public List<List<Integer>> resList = new ArrayList<List<Integer>>();
public List<List<Integer>> levelOrderBottom(TreeNode root) {
TreeNode node = root;
List<List<Integer>> result = new ArrayList<>();
if(node == null) return result;
Queue<TreeNode> queue = new LinkedList<TreeNode>();
queue.offer(node);
while(!queue.isEmpty()){
List<Integer> itemList = new ArrayList<Integer>();
int len = queue.size();
while(len > 0){
TreeNode tmpNode = queue.poll();
itemList.add(tmpNode.val);
if(tmpNode.left != null) queue.offer(tmpNode.left);
if(tmpNode.right != null) queue.offer(tmpNode.right);
len--;
}
resList.add(itemList);
}
for(int i = resList.size()-1; i >= 0; i--){
result.add(resList.get(i));
}
return result;
}
}
3题目链接:199. 二叉树的右视图 - 力扣(LeetCode)
思路:每层的最后一个值
class Solution {
public List<Integer> rightSideView(TreeNode root) {
List<Integer> list = new ArrayList<>();
Deque<TreeNode> que = new LinkedList<>();
if (root == null) {
return list;
}
que.offerLast(root);
while (!que.isEmpty()) {
int levelSize = que.size();
for (int i = 0; i < levelSize; i++) {
TreeNode poll = que.pollFirst();
if (poll.left != null) {
que.addLast(poll.left);
}
if (poll.right != null) {
que.addLast(poll.right);
}
//i是最后一个时才加入list
if (i == levelSize - 1) {
list.add(poll.val);
}
}
}
return list;
}
}
4题目链接:637. 二叉树的层平均值 - 力扣(LeetCode)
思路:内层while进去前会统计当前queue的size,在内层循环中计算sum,循环结束时计算平均值放入数组中
class Solution {
public List<Double> averageOfLevels(TreeNode root) {
List<Double> list = new ArrayList<>();
Deque<TreeNode> que = new LinkedList<>();
if(root == null) return list;
que.offerLast(root);
while(!que.isEmpty()){
int levelSize = que.size();
Double sum = 0.0;
for(int i = 0;i<levelSize;i++){
TreeNode poll = que.pollFirst();
sum += poll.val;
if(poll.left != null) que.addLast(poll.left);
if(poll.right != null) que.addLast(poll.right);
}
list.add(sum/levelSize);
}
return list;
}
}
5题目链接:429. N 叉树的层序遍历 - 力扣(LeetCode)
思路:左右孩子改成孩子遍历
class Solution {
public List<List<Integer>> levelOrder(Node root) {
List<List<Integer>> list = new ArrayList<>();
Deque<Node> que = new LinkedList<>();
if(root == null){
return list;
}
que.offerLast(root);
while(!que.isEmpty()){
int levelSize = que.size();
List<Integer> levelList = new ArrayList<>();
for(int i=0; i < levelSize; i++){
Node poll = que.pollFirst();
levelList.add(poll.val);
List<Node> children =poll.children;
if(children != null && children.size() != 0){
for(Node child : children){
if(child != null)
que.offerLast(child);
}
}
}
list.add(levelList);
}
return list;
}
}
6题目链接:515. 在每个树行中找最大值 - 力扣(LeetCode)
class Solution {
public List<Integer> largestValues(TreeNode root) {
if(root == null){
return Collections.emptyList();
}
List<Integer> result = new ArrayList();
Queue<TreeNode> queue = new LinkedList();
queue.offer(root);
while(!queue.isEmpty()){
int max = Integer.MIN_VALUE;
for(int i = queue.size(); i > 0; i--){
TreeNode node = queue.poll();
max = Math.max(max, node.val);
if(node.left != null) queue.offer(node.left);
if(node.right != null) queue.offer(node.right);
}
result.add(max);
}
return result;
}
}
7题目链接:116. 填充每个节点的下一个右侧节点指针 - 力扣(LeetCode)
思路:队列先进先出,双指针法,右孩子先进先出,指向右孩子
问题:cur和pre最初要指向同一个节点,不能是Node cur = que.poll();Node pre = que.poll();
class Solution {
public Node connect(Node root) {
Queue<Node> que = new LinkedList<Node>();
if(root == null) return root;
que.add(root);
while(que.size() != 0){
int size = que.size();
Node cur = que.poll();
Node pre = cur;
for(int i = 0; i<size; i++){
if(i != 0){
cur = que.poll();
cur.next = pre;
pre = cur;
}
if(cur.right != null) que.add(cur.right);
if(cur.left != null) que.add(cur.left);
}
}
return root;
}
}
8题目链接:117. 填充每个节点的下一个右侧节点指针 II - 力扣(LeetCode)
和上题一样,区别就是不是完全二叉树了
class Solution {
public Node connect(Node root) {
Queue<Node> que = new LinkedList<Node>();
if(root == null) return root;
que.add(root);
while(que.size() != 0){
int size = que.size();
Node cur = que.poll();
Node pre = cur;
for(int i = 0; i<size; i++){
if(i != 0){
cur = que.poll();
cur.next = pre;
pre = cur;
}
if(cur.right != null) que.add(cur.right);
if(cur.left != null) que.add(cur.left);
}
}
return root;
}
}
9题目链接:104. 二叉树的最大深度 - 力扣(LeetCode)
思路:最大深度等于层数
class Solution {
public int maxDepth(TreeNode root) {
if(root == null) return 0;
Queue<TreeNode> que = new LinkedList<>();
que.offer(root);
int depth = 0;
while(!que.isEmpty()){
int size = que.size();
while(size > 0){
TreeNode node = que.poll();
if(node.left != null) que.offer(node.left);
if(node.right != null) que .offer(node.right);
size--;
}
depth++;
}
return depth;
}
}
10题目链接:111. 二叉树的最小深度 - 力扣(LeetCode)
思路:最小深度等于左右孩子为空的节点所在层数
class Solution {
public int minDepth(TreeNode root) {
if(root == null) return 0;
Queue<TreeNode> que = new LinkedList<>();
int depth = 1;
que.offer(root);
while(!que.isEmpty()){
int size = que.size();
TreeNode node = que.poll();
for(int i = 0;i < size; i++){
if(node.left == null && node.right == null) return depth;
if(node.left != null) que.offer(node.left);
if(node.right !=null) que.offer(node.right);
}
depth++;
}
return depth;
}
}
226.翻转二叉树
题目链接:226. 翻转二叉树 - 力扣(LeetCode)
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 node = root.left;
root.left = root.right;
root.right = node;
return ;
}
}
总结:交换左右孩子就行,但是中序遍历不行,会重复交换左孩子,所以要进入两次左孩子,而不是进入左孩子;进入右孩子
101. 对称二叉树
题目链接:101. 对称二叉树 - 力扣(LeetCode)
思路:比较外侧,再比较内侧,两个左右孩子一起传进去
class Solution {
public boolean isSymmetric(TreeNode root) {
return compare(root.left,root.right);
}
public boolean compare(TreeNode left, TreeNode right){
if(left == null && right == null) return true;
if(left != null && right == null) return false;
if(left == null && right != null) return false;
if(left.val != right.val) return false;
boolean outSide = compare(left.left,right.right);
boolean inSide = compare(left.right,right.left);
return outSide && inSide;
}
}