leetcode刷题 117. 填充每个节点的下一个右侧节点指针 II,Medium (Java)BFS及优化

117. 填充每个节点的下一个右侧节点指针 II

  • 1.题目描述
  • 2.题解
    • 2.1 层次遍历也就是BFS
      • 2.1.1 思路
      • 2.1.2 Java代码
    • 2.2 使用已建立的 next 指针
      • 2.2.1 思路
      • 2.2.2 Java代码

1.题目描述

给定一个二叉树

struct Node {
int val;
Node *left;
Node *right;
Node *next;
}

填充它的每个 next 指针,让这个指针指向其下一个右侧节点。如果找不到下一个右侧节点,则将 next 指针设置为 NULL

初始状态下,所有 next 指针都被设置为 NULL

进阶:

  • 你只能使用常量级额外空间。
  • 使用递归解题也符合要求,本题中递归程序占用的栈空间不算做额外的空间复杂度。

示例:

leetcode刷题 117. 填充每个节点的下一个右侧节点指针 II,Medium (Java)BFS及优化_第1张图片

输入:root = [1,2,3,4,5,null,7]
输出:[1,#,2,3,#,4,5,7,#]
解释:给定二叉树如图 A 所示,你的函数应该填充它的每个 next 指针,以指向其下一个右侧节点,如图 B 所示。序列化输出按层序遍历顺序(由 next 指针连接),’#’ 表示每层的末尾。

提示:

  • 树中的节点数小于 6000
  • -100 <= node.val <= 100

来源:力扣(LeetCode)
链接:438. 找到字符串中所有字母异位词
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

2.题解

2.1 层次遍历也就是BFS

2.1.1 思路

这道题也就是层次遍历,然后按顺序链接,但是每层之间不连。\

  • 首先要了解二叉树使用BFS如何层次遍历:
    public void levelOrder(TreeNode tree) {
        if (tree == null)
            return;
        Queue<TreeNode> queue = new LinkedList<>();
        queue.add(tree);//相当于把数据加入到队列尾部
        while (!queue.isEmpty()) {
            //poll方法相当于移除队列头部的元素
            TreeNode node = queue.poll();
            System.out.println(node.val);
            if (node.left != null)
                queue.add(node.left);
            if (node.right != null)
                queue.add(node.right);
        }
    }

作者:sdwwld
  • 可以看出来是使用队列,将节点按顺序存进与取出实现层次遍历的。那本题就是再次基础上需要分辨哪一层,不然的话就会出现3—>next = 4这种情况。
  • 本题实现层的区分通过:在每层开始遍历之前取出每层的值,之后用循环一起遍历同一层的节点。在原代码的基础上增加了一层循环。而不是像原代码一样一个一个地遍历。
  • 而实现next的指向则是使用了一个哑节点,用来存储之前的节点。

2.1.2 Java代码

class Solution {
    public Node connect(Node root) {
        if(root == null){
            return root;
        }
        Queue<Node> queue= new LinkedList<Node>(); 
        queue.add(root);
        while(!queue.isEmpty()){
            int n = queue.size();
            Node temp = null;
            for(int i = 0;i<n;i++){
                Node first = queue.remove();
                if(first.left != null){
                    queue.add(first.left);
                }
                if(first.right != null){
                    queue.add(first.right);
                }
                if(i>0){
                    temp.next = first;
                }
                temp = first;
            }
        }
        return root;   
    }
}

2.2 使用已建立的 next 指针

2.2.1 思路

这个解法是基于前面BFS的解法改进而来,按题目的进阶要求实现了常量级的空间使用。
BFS使用了队列来实现层次遍历,我们已经知道一次for循环遍历的是一层,而本次解法就存储了start节点(也就是每层的第一个节点)来实现层的划分。
能用start节点是因为,next的链接在进行遍历之前已经完成了。

  • 首先需要一个previous节点来存储前一个节点,newStart节点存储下一层的起点
  • 之后在例如[1,2,3]的结构中,我们知道[2,3]是一层的,它们分别是1的左节点和右节点。
  • 当我们访问左节点时,将左节点存在previous上,同时判断newStart是否为空,是的话那这个节点也是newStart。
  • 到了右节点时,将previous.next指向 3 .此时我们就完成了第二层[2,3]的链接。并且newStart也更新为 2 .
  • 将start更新为newStart后,就可以进入[2,3]的左右节点的遍历。

看到这里会发现这个方法将queue存储的顺序,刚好用next指针来代替了。剩下的代码完全可以用BFS的逻辑去看,是一样的。

2.2.2 Java代码

class Solution {
    Node previous = null,newStart = null;
    public Node connect(Node root) {
        if(root == null){
            return root;
        }
        Node start = root;
        while(start != null){
            previous = null;
            newStart = null;
            for(Node temp = start;temp != null;temp = temp.next){
                if(temp.left != null){
                    handle(temp.left);
                }
                if(temp.right != null){
                    handle(temp.right);
                }
            }
            start = newStart;
        }
        return root;
    }
    public void handle(Node point){
        if(previous != null){
            previous.next = point;
        }
        if(newStart == null){
            newStart = point;
        }
        previous = point;
    }
}

你可能感兴趣的:(DFS&BFS,Leetcode刷题,Medium,leetcode,java)