LeetCode 102 层序遍历
层序遍历一般有两种方法:迭代和递归。对于递归来说:我们需要在每一次递归时传递深度,这样我们才能够知道这个节点应该被放在哪一层的集合当中。当我们发现结果的层数少于深度时,我们需要增加一个新的数组进入结果中。然后通过deep的值来将该节点放入对应的集合中。
public void func1(TreeNode root,int deep){
if(root==null) return ;
deep++;
if(res.size()<deep){
List<Integer> resList = new ArrayList<>();
res.add(resList);
}
res.get(deep-1).add(root.val);
func1(root.left,deep);
func1(root.right,deep);
}
对于迭代来说,我们利用了队列来解决。因为队列先进先出,所以我们可以先弹出已经进入的节点,然后把节点的左右子节点放入队列中,并储存结果,直至这一层节点都遍历结束。我们需要在最开始获取当前队列的长度len。每增加弹出一次节点就将len--;这样当len==0时,我们就遍历完了这一整层的数据。
public void func2(TreeNode root){
if(root==null)return ;
Queue<TreeNode> que = new LinkedList<>();
que.offer(root);
while(!que.isEmpty()){
int len = que.size();
ArrayList<Integer> list =new ArrayList<Integer>();
while(len>0){
TreeNode cur = que.poll();
list.add(cur.val);
if(cur.left!=null) que.offer(cur.left);
if(cur.right!=null) que.offer(cur.right);
len--;
}
res.add(list);
}
LeetCode 199 二叉树的右视图
这题我们用迭代的方式进行。
class Solution {
List<Integer> res = new ArrayList<>();
public List<Integer> rightSideView(TreeNode root) {
func1(root);
return res;
}
public void func1(TreeNode root){
if(root==null){
return ;
}
Queue<TreeNode> resList= new LinkedList<>();
resList.offer(root);
while(!resList.isEmpty()){
int len = resList.size();
for(int i=0;i<len;i++){
TreeNode cur = resList.poll();
if(cur.left!=null) resList.offer(cur.left);
if(cur.right!=null) resList.offer(cur.right);
if(i==len-1){
res.add(cur.val);
}
}
}
}
}
LeetCode 637 二叉树层的平均值
迭代
class Solution {
ArrayList<Double> res = new ArrayList<>();
public List<Double> averageOfLevels(TreeNode root) {
func1(root);
return res;
}
public void func1 (TreeNode root){
if(root==null){
return;
}
Queue<TreeNode> que = new LinkedList<>();
que.offer(root);
while(!que.isEmpty()){
int len = que.size();
double sum=0;
for(int i=0;i<len;i++){
TreeNode cur = que.poll();
sum+=cur.val;
if(cur.left!=null) que.offer(cur.left);
if(cur.right!=null) que.offer(cur.right);
}
res.add(sum/len);
}
}
}
LeetCode 429 N叉树的层序遍历
迭代法:和前面的方式基本相同,只不过因为它不再是左右节点而是一个节点的list,所以我们需要一次加入相应的节点。
class Solution {
List<List<Integer>> res = new ArrayList<>();
public List<List<Integer>> levelOrder(Node root) {
func1(root);
return res;
}
public void func1(Node root){
if(root==null) return ;
Queue<Node> que = new LinkedList<>();
que.offer(root);
while(!que.isEmpty()){
int len = que.size();
List<Integer> list = new ArrayList<>();
for(int i=0;i<len;i++){
Node cur = que.poll();
list.add(cur.val);
if(cur.children!=null&& cur.children.size()!=0){
int n = cur.children.size();
for(int j=0;j<n;j++){
que.offer(cur.children.get(j));
}
}
}
res.add(list);
}
}
}
LeetCode 515 在每个树行中找最大值
迭代:对每行的数进行一次比较,并把最大值放入结果中
class Solution {
List<Integer> res = new ArrayList<>();
public List<Integer> largestValues(TreeNode root) {
func1(root);
return res;
}
public void func1(TreeNode root){
if(root==null){
return ;
}
Queue<TreeNode> que = new LinkedList<>();
que.offer(root);
while(!que.isEmpty()){
int len= que.size();
int max = Integer.MIN_VALUE;
for(int i=0;i<len;i++){
TreeNode cur = que.poll();
if(cur.val>max){
max =cur.val;
}
if(cur.left!=null) que.offer(cur.left);
if(cur.right!=null) que.offer(cur.right);
}
res.add(max);
}
}
}
LeetCode 116.填充每个节点的下一个右侧节点指针
迭代:
需要在每一层开始之前记录一个cur节点,然后从第二个节点开始遍历,这样我们能够通过cur = next来记录前一个节点
class Solution {
public Node connect(Node root) {
func1(root);
return root;
}
public void func1(Node root){
if(root==null)return ;
Queue<Node> que = new LinkedList<>();
que.offer(root);
while(!que.isEmpty()){
int len = que.size();
Node cur = que.poll();
if(cur.left!=null) que.offer(cur.left);
if(cur.right!=null) que.offer(cur.right);
for(int i=1;i<len;i++){
Node next = que.poll();
if(next.left!=null) que.offer(next.left);
if(next.right!=null)que.offer(next.right);
cur.next= next;
cur = next;
}
}
}
}
LeetCode117.填充每个节点的下一个右侧节点指针II
需要考虑每层只有一个节点的情况
class Solution {
public Node connect(Node root) {
func1(root);
return root;
}
public void func1(Node root){
if(root==null)return ;
Queue<Node> que = new LinkedList<>();
que.offer(root);
while(!que.isEmpty()){
int len = que.size();
if(len==1){
Node cur = que.poll();
if(cur.left!=null) que.offer(cur.left);
if(cur.right!=null) que.offer(cur.right);
cur.next=null;
}else{
Node cur = que.poll();
if(cur.left!=null) que.offer(cur.left);
if(cur.right!=null) que.offer(cur.right);
for(int i=1;i<len;i++){
Node next= que.poll();
if(next.left!=null) que.offer(next.left);
if(next.right!=null) que.offer(next.right);
cur.next= next;
cur = next;
}
}
}
}
}
LeetCode 104.二叉树的最大深度
递归
class Solution {
int max = 0;
public int maxDepth(TreeNode root) {
func1(root,0);
return max;
}
public void func1(TreeNode root,int deep){
if(root==null){
return ;
}
deep++;
max = Math.max(deep,max);
func1(root.left,deep);
func1(root.right,deep);
}
}
LeetCode 111.二叉树的最小深度
迭代,当一个节点没有左右节点时直接返回结果
class Solution {
public int minDepth(TreeNode root) {
return func1(root);
}
public int func1(TreeNode root){
if(root==null){
return 0;
}
int deep=0;
Queue<TreeNode> que = new LinkedList<>();
que.offer(root);
while(!que.isEmpty()){
int len = que.size();
deep++;
for(int i=0;i<len;i++){
TreeNode cur = que.poll();
if(cur.left!=null) que.offer(cur.left);
if(cur.right!=null) que.offer(cur.right);
if(cur.left==null && cur.right==null) return deep;
}
}
return deep;
}
}
LeetCode226.翻转二叉树
迭代需要注意在交换位置应当在将左右子节点入栈之前
class Solution {
public TreeNode invertTree(TreeNode root) {
func2(root);
return root;
}
public void func1(TreeNode root){
if(root==null){
return;
}
TreeNode temp = root.left;
root.left= root.right;
root.right = temp;
func1(root.left);
func1(root.right);
}
public void func2(TreeNode root){
if(root==null){
return ;
}
Queue<TreeNode> que = new LinkedList<>();
que.offer(root);
while(!que.isEmpty()){
int len = que.size();
while(len>0){
TreeNode node = que.poll();
TreeNode temp = node.left;
node.left= node.right;
node.right = temp;
if(node.left!=null) que.offer(node.left);
if(node.right!=null) que.offer(node.right);
len--;
}
}
}
}