目录

  • I
    • 题目:
      • [剑指 Offer 32 - I. 从上到下打印二叉树](https://leetcode-cn.com/problems/cong-shang-dao-xia-da-yin-er-cha-shu-lcof/)
      • 题目分析
    • 初始解答:
    • 学习他人:
      • 方法一:
      • 方法二:
      • 方法三:
      • 方法四:
      • Stream简介
  • II
    • 题目:
      • [剑指 Offer 32 - II. 从上到下打印二叉树 II](https://leetcode-cn.com/problems/cong-shang-dao-xia-da-yin-er-cha-shu-ii-lcof/)
      • 题目分析
    • 初始解答:
    • 学习他人:
      • 方法一:
      • 方法二:
      • 方法三:
      • Java中的queue和deque
  • III
    • 题目:
      • [剑指 Offer 32 - III. 从上到下打印二叉树 III](https://leetcode-cn.com/problems/cong-shang-dao-xia-da-yin-er-cha-shu-iii-lcof/)
      • 题目分析
    • 初始解答:
    • 学习他人:
      • 方法一:
      • 方法二:
      • 方法三:
      • 方法四:
    • 总结

刷题日期:19:5225 星期四2021年4月8日

个人刷题记录,代码收集,来源皆为leetcode

经过多方讨论和请教,现在打算往Java方向发力

主要答题语言为Java

I

题目:

剑指 Offer 32 - I. 从上到下打印二叉树

难度中等79

从上到下打印出二叉树的每个节点,同一层的节点按照从左到右的顺序打印。

例如:
给定二叉树: [3,9,20,null,null,15,7],

    3/ \9  20/  \15   7

返回:

[3,9,20,15,7]

提示:

  1. 节点总数 <= 1000

题目分析

首先因为树的深度不确定,所以返回数组的长度也不一定,可以考虑用一个链表先存放数据,然后遍历链表定义数组返回。要么就得用类似于add这种添加命令不断加上新的子树节点。

其次因为是树的问题,首先想到递归解决,不断获取左右子树的节点内容,存储到返回数组。

层序遍历,又称广度优先搜索

初始解答:

因为暂时想不到解决数组长度的办法,而且这种遍历方式记的也不是很清楚,参考书和其他人的解答。

书上提到了用队列来解决问题,因为每次提出数据都需要先把它的左右子树放入队列。

层序遍历,参考了方法一

/*** Definition for a binary tree node.* public class TreeNode {*     int val;*     TreeNode left;*     TreeNode right;*     TreeNode(int x) { val = x; }* }*/
class Solution {public int[] levelOrder(TreeNode root) {//先考虑特殊情况if (root == null) return new int[0];//定义队列Queue<TreeNode> que = new LinkedList<TreeNode>();//定义数组List<Integer> list = new ArrayList<Integer>();//先把根节点放进去que.add(root); //入队,这里不放root.val,因为入队的就是节点while(!que.isEmpty()){ //这种特殊类型的数据是不是都有这个方法TreeNode node = que.poll(); //出队操作,建立树节点存放当前节点list.add(node.val); //列表的add属性,不用知道长度if(node.left != null) que.add(node.left); //先左if(node.right != null) que.add(node.right); //再右//所有节点都进入队列}//出队完毕,转换列表为数组return list.stream().mapToInt(Integer::intValue).toArray();//将Integer类型list复制为int数组 只不过使用了java8的stram新特性 //建议去了解一下stream 当然也可以直接写循环复制//流方法,不深究了}
}

效率比较低 执行结果:通过

显示详情

执行用时:4 ms, 在所有 Java 提交中击败了17.35%的用户

内存消耗:39 MB, 在所有 Java 提交中击败了5.02%的用户

参考了K神方法三后更直观的写法

/*** Definition for a binary tree node.* public class TreeNode {*     int val;*     TreeNode left;*     TreeNode right;*     TreeNode(int x) { val = x; }* }*/
class Solution {public int[] levelOrder(TreeNode root) {//先考虑特殊情况if (root == null) return new int[0];//定义队列,直接赋值写法,第二个尖括号里面的内容可省Queue<TreeNode> que = new LinkedList<>(){{ add(root); }};//定义数组ArrayList<Integer> list = new ArrayList<>();while(!que.isEmpty()){ //这种特殊类型的数据是不是都有这个方法TreeNode node = que.poll(); //出队操作,建立树节点存放当前节点list.add(node.val); //列表的add属性,不用知道长度if(node.left != null) que.add(node.left); //先左if(node.right != null) que.add(node.right); //再右//所有节点都进入队列}//出队完毕,转换列表为数组//更直观的写法//定义数组int[] res = new int[list.size()];//确定长短//列表数据转移到数组for(int i = 0; i < list.size(); i++) res[i] = list.get(i);return res;}
}

大概是没有调用流的原因,速度快了很多。执行结果: 通过

显示详情

执行用时:1 ms, 在所有 Java 提交中击败了99.74%的用户

内存消耗:38.7 MB, 在所有 Java 提交中击败了17.31%的用户

大家的思路都差不多,学习,主要还是队列这种的基本初始化都不清楚。

再默写一遍记忆写法,尤其是队列和列表的定义方法

/*** Definition for a binary tree node.* public class TreeNode {*     int val;*     TreeNode left;*     TreeNode right;*     TreeNode(int x) { val = x; }* }*/
class Solution {public int[] levelOrder(TreeNode root) {if (root == null) return new int [0];Queue<TreeNode> q = new LinkedList<>();q.add(root);ArrayList<Integer> l = new ArrayList<>();while (!q.isEmpty()) {TreeNode node = q.poll();l.add(node.val);if (node.left != null) q.offer(node.left);if (node.right != null) q.offer(node.right);}int [] res = new int[l.size()];for (int i = 0; i < l.size(); i++) res[i] = l.get(i);return res;}
}

学习他人:

方法一:

AmmoMercyL1 2020-04-08

简单的层序遍历

class Solution {public int[] levelOrder(TreeNode root) {if(root==null)return new int[0];Queue<TreeNode> queue=new LinkedList<TreeNode>();List<Integer> list=new ArrayList<Integer>();queue.add(root);while(!queue.isEmpty()){TreeNode node=queue.poll();list.add(node.val);if(node.left!=null)queue.add(node.left);if(node.right!=null)queue.add(node.right);}return list.stream().mapToInt(Integer::intValue).toArray();}
}

方法二:

wydxry 1 天前

执行结果: 通过 显示详情 执行用时: 1 ms , 在所有 Java 提交中击败了 99.74% 的用户 内存消耗: 38.5 MB , 在所有 Java 提交中击败了 76.48% 的用户

class Solution {public int[] levelOrder(TreeNode root) {List<Integer> res_=new ArrayList<Integer>();Queue<TreeNode> q = new LinkedList<TreeNode>();if(root==null){int[] res=new int[0];return res;}q.offer(root);while(q.peek()!=null){TreeNode tmp=q.poll();if(tmp.left!=null){q.offer(tmp.left);}if(tmp.right!=null){q.offer(tmp.right);}res_.add(tmp.val);}int[] res=new int[res_.size()];for(int i=0;i<res.length;i++){res[i]=res_.get(i);}return res;}
}

方法三:

题目要求的二叉树的 从上至下 打印(即按层打印),又称为二叉树的 广度优先搜索(BFS)。

BFS 通常借助 队列 的先入先出特性来实现。

K神 作者:jyd
链接:https://leetcode-cn.com/problems/cong-shang-dao-xia-da-yin-er-cha-shu-lcof/solution/mian-shi-ti-32-i-cong-shang-dao-xia-da-yin-er-ch-4/
来源:力扣(LeetCode)

class Solution {public int[] levelOrder(TreeNode root) {if(root == null) return new int[0];Queue<TreeNode> queue = new LinkedList<>(){{ add(root); }};ArrayList<Integer> ans = new ArrayList<>();while(!queue.isEmpty()) {TreeNode node = queue.poll();ans.add(node.val);if(node.left != null) queue.add(node.left);if(node.right != null) queue.add(node.right);}int[] res = new int[ans.size()];for(int i = 0; i < ans.size(); i++)res[i] = ans.get(i);return res;}
}

方法四:

夜尽天明…L1

(编辑过)2020-06-29

大佬(指K神),我看到网上的博客说,Queue使用时要尽量避免Collection的add()和remove()方法,而是要使用offer()来加入元素,使用poll()来获取并移出元素。它们的优点是通过返回值可以判断成功与否,add()和remove()方法在失败的时候会抛出异常。 修改完的代码如下:

class Solution {public int[] levelOrder(TreeNode root) {if (root == null) // 空树则返回空数组return new int[0];Queue<TreeNode> q = new LinkedList<> (); // 借助一个队列,通过 BFS 实现按层遍历二叉树ArrayList<Integer> tmp =new ArrayList<> (); // 申请一个动态数组 ArrayList 动态添加节点值q.offer(root); // 根结点先入队while (q.size() != 0) {TreeNode node = q.poll(); // 取出当前队首元素tmp.add(node.val); if(node.left != null) q.offer(node.left); // 左子节点入队if(node.right != null) q.offer(node.right); // 右子节点入队}// 将 ArrayList 转为 int数组并返回int[] res = new int[tmp.size()];for (int i=0; i<res.length; i++) {res[i] = tmp.get(i);}return res;}
}

Stream简介

作者:我是你的小眼睛儿
链接:https://www.jianshu.com/p/9fe8632d0bc2
来源:简书

为什么要使用Stream

自己再默写一遍,

II

题目:

剑指 Offer 32 - II. 从上到下打印二叉树 II

难度简单96

从上到下按层打印二叉树,同一层的节点按从左到右的顺序打印,每一层打印到一行。

例如:
给定二叉树: [3,9,20,null,null,15,7],

    3/ \9  20/  \15   7

返回其层次遍历结果:

[[3],[9,20],[15,7]
]

提示:

  1. 节点总数 <= 1000

题目分析

与第一题相比,增加了难度,返回的是分行的列表,那么难点就在于,如何定义二维的列表,只要这里通了,求解思路是类似的。

初始解答:

正好再一次复习相关存储方式的定义,一些地方没有了解过所以留下空白。

/*** Definition for a binary tree node.* public class TreeNode {*     int val;*     TreeNode left;*     TreeNode right;*     TreeNode(int x) { val = x; }* }*/
class Solution {public List<List<Integer>> levelOrder(TreeNode root) {//特殊情况if (root == null) return new List [0]; //不知道这种写法对不对//同样定义队列Queue<TreeNode> q = new LinkedList<>() {{ add(root); }};//定义列表,这次得是二维ArraylList<Integer> l = new ArraylList<>();int x = 0; //得有数据代表层数while (! q.isEmpty()) {TreeNode node = q.pull();l.add(node.val);if (node.left != null) q.offer(node.left);if (node.right != null) q.offer(node.right);}return l //如果l直接定义成二维列表的话,直接返回即可}
}

看了评论后大家好像并没有借鉴多少上一题的思路,也没有二维列表这一说法,不过方法二还是比较接近的,进行修改。

/*** Definition for a binary tree node.* public class TreeNode {*     int val;*     TreeNode left;*     TreeNode right;*     TreeNode(int x) { val = x; }* }*/
class Solution {public List<List<Integer>> levelOrder(TreeNode root) {//定义列表,这次得是二维List<List<Integer>> res = new ArrayList<>();//特殊情况if (root == null) return res; //不知道这种写法对不对//定义双向队列Deque<TreeNode> q = new ArrayDeque<>() {{ add(root); }};while (! q.isEmpty()) { //循环一次多一层的数据int size = q.size();//定义列表,每一层一个一维List<Integer> l = new ArrayList<>();// size对应在该层的子树个数,思路很巧妙while (size-- > 0) { //循环一次减一TreeNode node = q.poll();l.add(node.val);if (node.left != null) q.offer(node.left);if (node.right != null) q.offer(node.right);}res.add(l); //在列表的基础上加列表}return res; //如果l直接定义成二维列表的话,直接返回即可}
}

就是效率一般 执行结果:通过

显示详情

执行用时:2 ms, 在所有 Java 提交中击败了8.26%的用户

内存消耗:38.8 MB, 在所有 Java 提交中击败了15.44%的用户

K神的方法也是这种思路,不过第二层循环感觉还是K神比较简单一些

/*** Definition for a binary tree node.* public class TreeNode {*     int val;*     TreeNode left;*     TreeNode right;*     TreeNode(int x) { val = x; }* }*/
class Solution {public List<List<Integer>> levelOrder(TreeNode root) {//定义列表,这次得是二维List<List<Integer>> res = new ArrayList<>();//定义队列Queue<TreeNode> q = new LinkedList<>();//特殊情况if (root != null) q.add(root); while (! q.isEmpty()) { //循环一次多一层的数据//定义列表,每一层一个一维List<Integer> l = new ArrayList<>();// size对应在该层的子树个数,思路很巧妙for (int i = q.size(); i > 0; i--) { //为什么必须是递减的顺序//    for (int i = 0; i < q.size(); i++) { //这样就会解答错误,因为在循环中q.size()已经改变,for循环第一项只用一次,如果放在第二项,就会连续判断新的size,所以出错TreeNode node = q.poll();l.add(node.val);if (node.left != null) q.offer(node.left);if (node.right != null) q.offer(node.right);}res.add(l); //在列表的基础上加列表}return res; //如果l直接定义成二维列表的话,直接返回即可}
}

少用了一个size,效果立马就好了。执行结果:通过

显示详情

执行用时:1 ms, 在所有 Java 提交中击败了94.50%的用户

内存消耗:38.7 MB, 在所有 Java 提交中击败了46.42%的用户

学习方法一的递归解法:

/*** Definition for a binary tree node.* public class TreeNode {*     int val;*     TreeNode left;*     TreeNode right;*     TreeNode(int x) { val = x; }* }*/
class Solution {List<List<Integer>> res = new ArrayList(); //双层列表,注意这里没有尖括号public List<List<Integer>> levelOrder(TreeNode root) {recur(root,0);return res;}public void recur(TreeNode root, int k) {if (root != null) {if (res.size() <= k) res.add(new ArrayList());res.get(k).add(root.val);recur(root.left, K+1);recur(root.right, K+1);}}
}

明明就是按着来的,就是报错

几乎一样的代码上面的不行,下面的就可以

/*** Definition for a binary tree node.* public class TreeNode {*     int val;*     TreeNode left;*     TreeNode right;*     TreeNode(int x) { val = x; }* }*/
class Solution {List<List<Integer>> res = new ArrayList(); //双层列表,注意这里没有尖括号public List<List<Integer>> levelOrder(TreeNode root) {recur(root, 0);return res;}public void recur(TreeNode root, int k) {if (root != null) {if (res.size() <= k) res.add(new ArrayList());res.get(k).add(root.val);recur(root.left, K+1);recur(root.right, K+1);}}
}
/
class Solution {List<List<Integer>> res = new ArrayList();public List<List<Integer>> levelOrder(TreeNode root) {recur(root, 0);return res;}public void recur(TreeNode root, int k) {if (root != null) {if (res.size() <= k) res.add(new ArrayList());res.get(k).add(root.val);recur(root.left, k+1);recur(root.right, k+1);}}
}

最后找到bug在输入k+式shift按早了,打成K+了,不知道你们能不能看出来大小写k和K的区别,我是瞎了已经

/*** Definition for a binary tree node.* public class TreeNode {*     int val;*     TreeNode left;*     TreeNode right;*     TreeNode(int x) { val = x; }* }*/
class Solution {List<List<Integer>> res = new ArrayList(); //双层列表,注意这里没有尖括号public List<List<Integer>> levelOrder(TreeNode root) {recur(root, 0);return res;}public void recur(TreeNode root, int k) {if (root != null) {if (res.size() <= k) res.add(new ArrayList());res.get(k).add(root.val);recur(root.left, k+1);recur(root.right, k+1);//好家伙,小写k和大写K的区别}}
}

速度是真快 执行结果:通过

显示详情

执行用时:0 ms, 在所有 Java 提交中击败了100.00%的用户

内存消耗:39 MB, 在所有 Java 提交中击败了5.00%的用户

学习他人:

方法一:

活动假人 2020-04-06

java 递归层次遍历

class Solution {List<List<Integer>> node=new ArrayList();public List<List<Integer>> levelOrder(TreeNode root) {lei(root,0);return node;}public void lei(TreeNode root,int k){if(root!=null){if(node.size()<=k)node.add(new ArrayList());node.get(k).add(root.val);lei(root.left,k+1);lei(root.right,k+1);}}
}

方法二:

fireworksL1

2020-10-11

class Solution {/**层次遍历*/public List<List<Integer>> levelOrder(TreeNode root) {List<List<Integer>> res = new ArrayList<>();if(root == null){return res;}Deque<TreeNode> queue = new ArrayDeque<>();queue.offer(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.offer(node.left);}if(node.right != null){queue.offer(node.right);}}  res.add(list);}return res;}
}

方法三:

K神 作者:jyd
链接:https://leetcode-cn.com/problems/cong-shang-dao-xia-da-yin-er-cha-shu-ii-lcof/solution/mian-shi-ti-32-ii-cong-shang-dao-xia-da-yin-er-c-5/
来源:力扣(LeetCode)

class Solution {public List<List<Integer>> levelOrder(TreeNode root) {Queue<TreeNode> queue = new LinkedList<>();List<List<Integer>> res = new ArrayList<>();if(root != null) queue.add(root);while(!queue.isEmpty()) {List<Integer> tmp = new ArrayList<>();for(int i = queue.size(); i > 0; i--) {TreeNode node = queue.poll();tmp.add(node.val);if(node.left != null) queue.add(node.left);if(node.right != null) queue.add(node.right);}res.add(tmp);}return res;}
}

Java中的queue和deque

队列(queue)是一种常用的数据结构,可以将队列看做是一种特殊的线性表,该结构遵循的先进先出原则。Java中,LinkedList实现了Queue接口,因为LinkedList进行插入、删除操作效率较高
相关常用方法:

双向队列(Deque),是Queue的一个子接口,双向队列是指该队列两端的元素既能入队(offer)也能出队(poll),如果将Deque限制为只能从一端入队和出队,则可实现栈的数据结构。对于栈而言,有入栈(push)和出栈(pop),遵循先进后出原则

常用方法如下:

III

题目:

剑指 Offer 32 - III. 从上到下打印二叉树 III

难度中等90

请实现一个函数按照之字形顺序打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右到左的顺序打印,第三行再按照从左到右的顺序打印,其他行以此类推。

例如:
给定二叉树: [3,9,20,null,null,15,7],

    3/ \9  20/  \15   7

返回其层次遍历结果:

[[3],[20,9],[15,7]
]

提示:

  1. 节点总数 <= 1000

题目分析

这种是不是就得用栈和队列来交替解答了,先队列再栈,最后再合并。

初始解答:

感觉就是很绝望,一道题原来能玩出来这么多花样,参考上一道题改的

/*** Definition for a binary tree node.* public class TreeNode {*     int val;*     TreeNode left;*     TreeNode right;*     TreeNode(int x) { val = x; }* }*/
class Solution {public List<List<Integer>> levelOrder(TreeNode root) {Queue<TreeNode> queue = new LinkedList<>();List<List<Integer>> res = new ArrayList<>();if(root != null) queue.add(root);int ord = 0;while(!queue.isEmpty()) {List<Integer> tmp = new ArrayList<>();for(int i = queue.size(); i > 0; i--) {TreeNode node = queue.poll();tmp.add(node.val);if (ord % 2 == 1) {if(node.left != null) queue.add(node.left);if(node.right != null) queue.add(node.right);} else {if(node.right != null) queue.add(node.right);if(node.left != null) queue.add(node.left);}}ord ++;res.add(tmp);}return res;}
}

解答出现了错误 执行结果:

解答错误显示详情

输入:[1,2,3,4,null,null,5]

输出:[[1],[3,2],[5,4]]

预期结果:[[1],[3,2],[4,5]]

换用Java自带方法,参考方法一

/*** Definition for a binary tree node.* public class TreeNode {*     int val;*     TreeNode left;*     TreeNode right;*     TreeNode(int x) { val = x; }* }*/
class Solution {public List<List<Integer>> levelOrder(TreeNode root) {//定义列表,这次得是二维List<List<Integer>> res = new ArrayList<>();//定义队列Queue<TreeNode> q = new LinkedList<>();//特殊情况int level=1;if (root != null) q.add(root); while (! q.isEmpty()) { //循环一次多一层的数据//定义列表,每一层一个一维List<Integer> l = new ArrayList<>();// size对应在该层的子树个数,思路很巧妙for (int i = q.size(); i > 0; i--) { //为什么必须是递减的顺序//    for (int i = 0; i < q.size(); i++) { //这样就会解答错误,因为在循环中q.size()已经改变,for循环第一项只用一次,如果放在第二项,就会连续判断新的size,所以出错TreeNode node = q.poll();l.add(node.val);if (node.left != null) q.offer(node.left);if (node.right != null) q.offer(node.right);}if(level%2==0) Collections.reverse(l);//反转方法res.add(l); //在列表的基础上加列表level++;}return res; //如果l直接定义成二维列表的话,直接返回即可}
}

效率不高 执行结果:通过

显示详情

执行用时:2 ms, 在所有 Java 提交中击败了26.96%的用户

内存消耗:38.9 MB, 在所有 Java 提交中击败了6.50%的用户

不折腾了,有兴趣分析的直接看方法四K神的分析即可

学习他人:

方法一:

offer来碗里L1 2021-03-20

class Solution {public List<List<Integer>> levelOrder(TreeNode root) {List<List<Integer>> res=new ArrayList<>();if(root==null) return res;Queue<TreeNode> q=new LinkedList<>();q.offer(root);int level=1;while(!q.isEmpty()){List<Integer> list=new ArrayList<>();int size=q.size();for(int i=0;i<size;i++){TreeNode node=q.poll();list.add(node.val);if(node.left!=null) q.offer(node.left);if(node.right!=null) q.offer(node.right);}if(level%2==0) Collections.reverse(list);res.add(list);level++;}return res;}

方法二:

WUTerL1

2021-02-23

详细注释+代码

/*** 要求:请实现一个函数按照之字形顺序打印二叉树,即第一行按照从左到右的顺序打印,*      第二层按照从右到左的顺序打印,第三行再按照从左到右的顺序打印,其他行以此类推* @param root 二叉树根结点* @return 结果* 方法:层序遍历 + 双端队列,奇数层(第一层为1)从首结点到尾结点,依次添加到集合中,新结点依次添加到队列尾部;*      偶数层从尾结点到首结点依次添加到集合中,新结点依次添加到首部*/public static List<List<Integer>> levelOrder(TreeNode root) {// 结果List<List<Integer>> res = new ArrayList<>();// 判空if (root == null) {return res;}// 层序遍历辅助队列Deque<TreeNode> deque = new LinkedList<>();deque.add(root);// 打印顺序标志,初始值表示从左开始boolean isLeft = true;// 遍历二叉树while (!deque.isEmpty()) {// 单独一层的结果List<Integer> ans = new ArrayList<>();// 得到此时队列中结点的个数,即当前层的结点数int count = deque.size();// 遍历队列中的结点,并将下一层的结点入队for (int i = 0; i < count; i++) {// 队列中的元素始终按照每一层的结点的相对位置顺序存储,只是在遍历分别从头结点开始或者从尾结点开始if (isLeft) {// 从头结点开始,并把新结点添加到尾部TreeNode dequeHead = deque.peekFirst();ans.add(dequeHead.val);// 先左后右if (dequeHead.left != null) {deque.addLast(dequeHead.left);}if (dequeHead.right != null) {deque.addLast(dequeHead.right);}// 删除首元素deque.removeFirst();}else {// 从尾结点开始,并且将新结点添加到首部TreeNode dequeHead = deque.peekLast();ans.add(dequeHead.val);// 先右后左if (dequeHead.right != null) {deque.addFirst(dequeHead.right);}if (dequeHead.left != null) {deque.addFirst(dequeHead.left);}// 删除尾元素deque.removeLast();}}// 将单层结果添加到结果集合中res.add(ans);// 顺序取反isLeft = !isLeft;}return res;}

方法三:

麦宇恒 2020-02-15 递归

class Solution {List<List<Integer>> res=new ArrayList<>();public List<List<Integer>> levelOrder(TreeNode root) {helper(root,0);return res;}private void helper(TreeNode root,int level){if(root==null)return;if(res.size()==level){res.add(new ArrayList<>());}if(level%2==0){res.get(level).add(root.val);}else{res.get(level).add(0,root.val);}helper(root.left,level+1);helper(root.right,level+1);}
}

方法四:

K神

方法一:层序遍历 + 双端队列

利用双端队列的两端皆可添加元素的特性,设打印列表(双端队列) tmp ,并规定:

奇数层 则添加至 tmp 尾部 ,

偶数层 则添加至 tmp 头部 。

作者:jyd
链接:https://leetcode-cn.com/problems/cong-shang-dao-xia-da-yin-er-cha-shu-iii-lcof/solution/mian-shi-ti-32-iii-cong-shang-dao-xia-da-yin-er–3/
来源:力扣(LeetCode)

class Solution {public List<List<Integer>> levelOrder(TreeNode root) {Queue<TreeNode> queue = new LinkedList<>();List<List<Integer>> res = new ArrayList<>();if(root != null) queue.add(root);while(!queue.isEmpty()) {LinkedList<Integer> tmp = new LinkedList<>();for(int i = queue.size(); i > 0; i--) {TreeNode node = queue.poll();if(res.size() % 2 == 0) tmp.addLast(node.val); // 偶数层 -> 队列尾部else tmp.addFirst(node.val); // 奇数层 -> 队列头部if(node.left != null) queue.add(node.left);if(node.right != null) queue.add(node.right);}res.add(tmp);}return res;}
}

方法二:层序遍历 + 双端队列(奇偶层逻辑分离)

方法一代码简短、容易实现;但需要判断每个节点的所在层奇偶性,即冗余了 NN 次判断。

通过将奇偶层逻辑拆分,可以消除冗余的判断。

class Solution {public List<List<Integer>> levelOrder(TreeNode root) {Deque<TreeNode> deque = new LinkedList<>();List<List<Integer>> res = new ArrayList<>();if(root != null) deque.add(root);while(!deque.isEmpty()) {// 打印奇数层List<Integer> tmp = new ArrayList<>();for(int i = deque.size(); i > 0; i--) {// 从左向右打印TreeNode node = deque.removeFirst();tmp.add(node.val);// 先左后右加入下层节点if(node.left != null) deque.addLast(node.left);if(node.right != null) deque.addLast(node.right);}res.add(tmp);if(deque.isEmpty()) break; // 若为空则提前跳出// 打印偶数层tmp = new ArrayList<>();for(int i = deque.size(); i > 0; i--) {// 从右向左打印TreeNode node = deque.removeLast();tmp.add(node.val);// 先右后左加入下层节点if(node.right != null) deque.addFirst(node.right);if(node.left != null) deque.addFirst(node.left);}res.add(tmp);}return res;}
}

方法三:层序遍历 + 倒序

此方法的优点是只用列表即可,无需其他数据结构。

偶数层倒序: 若 res 的长度为 奇数 ,说明当前是偶数层,则对 tmp 执行 倒序 操作。

class Solution {public List<List<Integer>> levelOrder(TreeNode root) {Queue<TreeNode> queue = new LinkedList<>();List<List<Integer>> res = new ArrayList<>();if(root != null) queue.add(root);while(!queue.isEmpty()) {List<Integer> tmp = new ArrayList<>();for(int i = queue.size(); i > 0; i--) {TreeNode node = queue.poll();tmp.add(node.val);if(node.left != null) queue.add(node.left);if(node.right != null) queue.add(node.right);}if(res.size() % 2 == 1) Collections.reverse(tmp);res.add(tmp);}return res;}
}

总结

以上就是本题的内容和学习过程了,变体太多了,这才叫举一反三吧,太强了。

奇偶这个真是妙蛙种子吃着妙脆角进了米奇妙妙屋,妙到家了。

欢迎讨论,共同进步。

【剑指Offer】个人学习笔记_32_从上到下打印二叉树 IIIIII相关推荐

  1. 剑指offer——面试题23:从上往下打印二叉树

    剑指offer--面试题23:从上往下打印二叉树 Solution1: 典型的BFS算法! 思路一开始没想到,按照书上的思路写的答案... 注意:deque是双向队列,在头尾插入都很快! /* str ...

  2. 剑指offer(Java实现) 从上往下打印二叉树

    题目描述 从上往下打印出二叉树的每个节点,同层节点从左至右打印. 解题思路 利用队列(链表)辅助实现. 代码实现 import java.util.ArrayList; import java.uti ...

  3. 剑指offer二十二之从上往下打印二叉树

    一.题目 从上往下打印出二叉树的每个节点,同层节点从左至右打印. 二.思路 二叉树的层次遍历,可以借助队列实现.具体思路详见注释. 三.代码 import java.util.ArrayList; i ...

  4. 剑指offer面试题23:从上到下打印二叉树(树的层序遍历)

    题目:从上往下打印出二叉树的每个节点,同一层的结点按照从左往右的顺序打印. 解题思路:二叉树的层序遍历,在打印一个节点的时候,要把他的子节点保存起来打印第一层要把第二层的节点保存起来, 打印第二层要把 ...

  5. [剑指offer]面试题23:从上往下打印二叉树

    面试题23:从上往下打印二叉树 题目:从上往下打印出二叉树的每个结点,同一层的结点按照从左到右的顺序打印.例如输入图4.5中的二叉树,则依次打印出8.6.10.5.7.9.11. 二叉树结点的定义如下 ...

  6. 剑指Offer - 面试题32 - III. 从上到下打印二叉树 III(BFS,queue+stack)

    1. 题目 请实现一个函数按照之字形顺序打印二叉树, 即第一行按照从左到右的顺序打印, 第二层按照从右到左的顺序打印, 第三行再按照从左到右的顺序打印,其他行以此类推. 例如: 给定二叉树: [3,9 ...

  7. 剑指Offer - 面试题32 - I. 从上到下打印二叉树(按层BFS遍历,queue)

    1. 题目 从上到下打印出二叉树的每个节点,同一层的节点按照从左到右的顺序打印. 例如: 给定二叉树: [3,9,20,null,null,15,7],3/ \9 20/ \15 7 返回: [3,9 ...

  8. 剑指offer面试题32 - III. 从上到下打印二叉树 III(二叉树)(BFS)

    题目描述 请实现一个函数按照之字形顺序打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右到左的顺序打印,第三行再按照从左到右的顺序打印,其他行以此类推. 思路 详见链接 代码 class So ...

  9. 剑指offer面试题32 - I. 从上到下打印二叉树(二叉树)(BFS)

    题目描述 从上到下打印出二叉树的每个节点,同一层的节点按照从左到右的顺序打印. 思路 详见链接 代码 class Solution:def levelOrder(self, root:TreeNode ...

最新文章

  1. 【高并发】一个工作了7年的朋友去面试竟然被Thread类虐的体无完肤
  2. 三大缓存框架ehcache、memcache和redis的介绍
  3. [uEnv.txt]在uEnv.txt文件中使用if语句实现Image/dtb文件切换
  4. 蓝桥杯 十进制数转八进制数
  5. Python学习系列day2-python基础
  6. 格兰杰因果关系检验_混频(mixed frequency)数据的格兰杰因果(Grange causality)检验及其Matlab实现...
  7. iOS开发-网络-合理封装请求接口
  8. 图像分类——EfficientNet的学习笔记
  9. 2022最新版sci和ssci双检索期刊,详细期刊目录值得了解!
  10. 发电厂计算机监控课,那比水利发电厂监控系统课件.ppt
  11. Flowchat 流程图在Markdown中的使用(不同编辑器有细微区别)
  12. 卸载Docker CE
  13. 通过漫画学习MySQL索引及优化
  14. 魔教传奇—阿里软件的魔方文化
  15. QCC---Host configure tools
  16. 安装iso格式的软件安装程序
  17. python中文件的导入与导出
  18. 运用css3新属性transform写的盒子嵌套展开动画效果
  19. ABAP 发布webservice调用外部webservice
  20. 数值分析实验 实验3-1 牛顿下山法 python3实现

热门文章

  1. python pptx库中文文档_python-pptx使用说明
  2. 给职场年轻人的一些建议
  3. 电磁兼容(EMC)设计如何融入产品研发流程~系统流程法
  4. 抢在时间前面的7条捷径阅读笔记
  5. 聚焦采购数字化,企企通受邀出席中国上海采购-供应链间接采购年会
  6. 0x00007FF727D8013F 处有未经处理的异常(在 bigship.exe 中): 0xC0000005: 读取位
  7. web开发中经常使用到的代码(csdn中下载的资源)
  8. HoloLens开发笔记-制作传送门
  9. java 声明一个bus类_Java初级阶段测试附带答案
  10. dpi是什么?如何更改dpi?(仅个人笔记,可能有误)