资讯专栏INFORMATION COLUMN

[Leetcode] Populating Next Right Pointers in Each

miracledan / 1136人阅读

摘要:原题链接广度优先搜索复杂度时间空间思路相当于是遍历二叉树。代码记录本层节点的个数最后一个节点的是,不做处理递归法复杂度时间空间递归栈空间思路由于父节点多了指针,我们不用记录父节点的父节点就能直到它相邻的节点。

Populating Next Right Pointers in Each Node I

Given a binary tree

struct TreeLinkNode {
  TreeLinkNode *left;
  TreeLinkNode *right;
  TreeLinkNode *next;
}

Populate each next pointer to point to its next right node. If there
is no next right node, the next pointer should be set to NULL.

Initially, all next pointers are set to NULL.
For example, Given the following perfect binary tree,

     1
   /  
  2    3
 /   / 
4  5  6  7

After calling your function, the tree should look like:

     1 -> NULL
   /  
  2 -> 3 -> NULL
 /   / 
4->5->6->7 -> NULL

Note:

You may only use constant extra space. You may assume that it is a
perfect binary tree (ie, all leaves are at the same level, and every
parent has two children).

原题链接

广度优先搜索 复杂度

时间 O(N) 空间 O(N)

思路

相当于是Level Order遍历二叉树。通过一个Queue来控制每层的遍历,注意处理该层最后一个节点的特殊情况。此方法同样可解第二题。

代码
public class Solution {
    public void connect(TreeLinkNode root) {
        Queue q = new LinkedList();
        if(root!=null) q.offer(root);
        while(!q.isEmpty()){
            //记录本层节点的个数
            int size = q.size();
            for(int i = 0; i < size; i++){
                TreeLinkNode curr = q.poll();
                //最后一个节点的next是null,不做处理
                if(i < size - 1){
                    TreeLinkNode next = q.peek();
                    curr.next = next;
                }
                if(curr.left != null) q.offer(curr.left);
                if(curr.right != null) q.offer(curr.right);
            }
        }
    }
}
递归法 复杂度

时间 O(N) 空间 O(N) 递归栈空间

思路

由于父节点多了next指针,我们不用记录父节点的父节点就能直到它相邻的节点。对于左子节点来说,其next节点就是父节点的右节点。对于右子节点来说i,其next节点就是父节点的next节点的左子节点。以此递归。

代码
public class Solution {
    public void connect(TreeLinkNode root) {
        if(root == null) return;
        //左子节点的next是右子节点
        if(root.left != null) root.left.next = root.right;
        if(root.right != null){
        //右子节点的next是父节点的next的左子节点
            root.right.next = root.next == null? null:root.next.left;
        }
        connect(root.left);
        connect(root.right);
    }
}
双指针法 Two Pointers 复杂度

时间 O(N) 空间 O(1)

思路

上述两种方法都会使用额外空间。实际上,我们可以用一个指针记录当前层内遍历到的节点,另一个指针记录下一层第一个节点,来省去空间开销。这样,我们可以基于上一层的next指针进行横向遍历,同时遍历到该层尽头时又能使用记录下的下一层第一个节点的指针来直接跳转到下一层。

代码
public class Solution {
    public void connect(TreeLinkNode root) {
        if(root == null) return;
        //记录该层当前节点的指针,也叫做父节点,我们通过遍历父节点,来连接它们的子节点
        TreeLinkNode p = root;
        //记录下层第一个节点的指针
        TreeLinkNode first = null;
        while(p != null){
            //当first为空时,说明刚跳转到新的一层,需要设置下一层的第一个节点了
            if(first == null){
                first = p.left;
            }
            //如果有左子节点,则其next是右子节点,如果没有,则遍历结束
            //因为我们实际上是将下一层的节点用next指针连接,所以当遍历到叶子结点时已经没有下一层
            if(p.left != null){
                p.left.next = p.right; 
            } else {
                break;
            }
            //如果父节点有next,则next的左子节点是父节点的右子节点的next,如果没有,说明这层遍历完了,转入下一层
            if(p.next != null){
                p.right.next = p.next.left;
                p = p.next;
            } else {
                p = first;
                first = null;
            }
        }
    }
}
层次递进法 复杂度

时间 O(N) 空间 O(1)

思路

因为我们确定的知道每个非叶子节点都有左右节点,所以我们可以一层一层链接。只要根据当前层的next指针形成的链表,将下一层的左右左右连起来就行了。

代码
public class Solution {
    public void connect(TreeLinkNode root) {
        TreeLinkNode head = root;
        while(head != null){
            // 记录当层第一个节点
            TreeLinkNode tmpHead = head;
            // 开始链接下一层
            while(head != null){
                //链接左节点
                if(head.left != null) head.left.next = head.right;
                //链接右节点
                if(head.right != null) head.right.next = head.next != null ? head.next.left : null;
                head = head.next;
            }
            // 跳到下一层第一个节点
            head = tmpHead.left;
        }
    }
}
Populating Next Right Pointers in Each Node II

Follow up for problem "Populating Next Right Pointers in Each Node".

What if the given tree could be any binary tree? Would your previous
solution still work?

Note:

You may only use constant extra space. For example, Given the
following binary tree,

     1
   /  
  2    3
 /     
4   5    7 

After calling your function, the tree should look like:

     1 -> NULL
   /  
  2 -> 3 -> NULL
 /     
4-> 5 -> 7 -> NULL

原题链接

递归法 复杂度

时间 O(N) 空间 O(N) 递归栈空间

思路

由于父节点多了next指针,我们不用记录父节点的父节点就能直到它相邻的节点。对于左子节点来说,其next节点就是父节点的右节点。对于右子节点来说i,其next节点就是父节点的next节点的左子节点。以此递归。

代码
public class Solution {
    public void connect(TreeLinkNode root) {
        if(root == null) return;
        if(root.left != null) root.left.next = root.right;
        if(root.right != null){
            root.right.next = root.next == null? null:root.next.left;
        }
        connect(root.left);
        connect(root.right);
    }
}
三指针法 Three Pointers 复杂度

时间 O(N) 空间 O(1)

思路

当不是完全二叉树时,左子节点或者右子节点都有可能为空,每个叶子节点的深度也不一定相同,所以退出循环的条件、每层头节点的确定方法以及next指针的赋值都要改变。首先,next指针不再是分左右子节点来直接赋值,而是对记录下来的上个节点的next赋当前操作的节点。其次,退出循环不能再像上一题一样到最后一层就可以退出,因为当前节点会不断更新,只有当前节点为空时才能退出。最后头节点可能是左子节点,也可能是右子节点。

代码
public class Solution {
    public void connect(TreeLinkNode root) {
        if(root == null) return;
        TreeLinkNode p = root;
        TreeLinkNode first = null;
        //上一个节点,我们给上一个节点的next赋值,然后再更新上一个节点为它的next
        TreeLinkNode last = null;
        while(p != null){
            //下一层的头节点有可能是左子节点也有可能是右子节点
            if(first == null){
                if(p.left != null){
                    first = p.left;
                } else if(p.right != null){
                    first = p.right;
                }
            }
            //更新last和last的next
            if(p.left != null){
                if(last != null){
                    last.next = p.left;
                }
                last = p.left;
            }
            if(p.right != null){
                if(last != null){
                    last.next = p.right;
                }
                last = p.right;
            }
            //如果当前节点没有next,则该层结束,转入下一层,否则就继续
            if(p.next != null){
                p = p.next;
            } else {
                p = first;
                first = null;
                last = null;
            }
            
        }
    }
}
层次递进法 复杂度

时间 O(N) 空间 O(1)

思路

第一问层次递进的延伸。上一问中我们不需要一个额外的指针来控制我们一层中链接的节点,因为我们知道肯定是左右左右的顺序,而这题中左右节点可能不存在,所有我们要用一个指针记录这一层中我们链接到了哪个节点,方便我们链接下一个节点。

代码
public class Solution {
    public void connect(TreeLinkNode root) {
        // head是上一层的节点,我们用上一层节点的next形成链表,来链接当前这层
        TreeLinkNode head = root;
        while(head != null){
            // 记录链接到哪个节点的额外指针
            TreeLinkNode curr = new TreeLinkNode(0);
            // tmp指向该层的第一节点
            TreeLinkNode tmp = curr;
            while(head != null){
                // 尝试链接左节点
                if(head.left != null){
                    curr.next = head.left;
                    curr = curr.next;
                }
                // 尝试链接右节点
                if(head.right != null){
                    curr.next = head.right;
                    curr = curr.next;
                }
                head = head.next;
            }
            // 将head移动到当前这层的的第一个,准备链接下一层
            head = tmp.next;
        }
    }
}

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/66157.html

相关文章

  • leetcode116-117. Populating Next Right Pointers in

    摘要:题目要求给一个完全二叉树,将当前节点的值指向其右边的节点。而在中则是提供了一个不完全的二叉树,其它需求没有发生改变。我们需要使用一个变量来存储父节点,再使用一个变量来存储当前操作行的,将前一个指针指向当前父节点的子节点。 题目要求 Given a binary tree struct TreeLinkNode { TreeLinkNode *left; ...

    coolpail 评论0 收藏0
  • 117. Populating Next Right Pointers In Each NodeII

    题目:Follow up for problem Populating Next Right Pointers in Each Node. What if the given tree could be any binary tree? Would your previous solution still work? Note: You may only use constant extra sp...

    jackwang 评论0 收藏0
  • LeetCode[117] Population Next Right Pointers in Ea

    摘要:复杂度思路设置一个指向下一层要遍历的节点的开头的位置。 LeetCode[117] Population Next Right Pointers in Each Node II 1 / 2 3 / 4 5 7 After calling your function, the tree should look like: ...

    lijinke666 评论0 收藏0
  • [LeetCode] 426. Convert BST to Sorted Doubly Linke

    Problem Convert a BST to a sorted circular doubly-linked list in-place. Think of the left and right pointers as synonymous to the previous and next pointers in a doubly-linked list. Lets take the foll...

    MartinDai 评论0 收藏0
  • [Leetcode] Two Sum 两数和

    摘要:如果存在该差值,说明存在两个数之和是目标和。而哈希表方法中的则可以换成。如果要求的不是两个数和和,而是找两个数之差为特定值的配对呢同样用哈希表可以解决。 Two Sum Given an array of integers, find two numbers such that they add up to a specific target number.The function t...

    pkhope 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<