116.填充每一个节点的next指针

题目链接

题解

递归算法

递归算法就需要思考整个流程能否分割成若干个小项目,将小项目完成并联合起来就完成了大项目,所以将问题细化的思维很重要。
观察下面的这幅图:
在这里插入图片描述
很容易得出规律是:每一个节点的左右子节点互相连接,然后得到这样的思路:

connect(Node root) {
    
    
    if root is None {
    
    
        return root
    }
	# 每一个父节点的左右结点连接
    root.left.next = root.right
	# 将左节点作为父节点重复上述步骤
    connect(root.left)
    # 将右节点作为父节点重复上述步骤
    connect(root.right)
    return root
}

但是这样有个问题,思考一下这样仅仅能够联系的位于同一个父节点下的左右结点,对于异父相邻节点是无法连接的,而异父相邻节点涉及到两个不同的父节点,所以如果要使用递归来实现,必然涉及到两个不同的父节点的传递,且这两个父节点之间的关系是同一层且相邻的关系。现在所给函数只有一个参数传入,所以需要自己构造辅助函数来传递两个结点实现:


class Solution:
    def connectTwo(self, node1, node2):
        if node1 is None or node2 is None:
            return None, None
        # 相邻节点连接
        node1.next = node2
        # 传入同一个父节点的左右结点
        self.connectTwo(node1.left, node1.right)
        # 传入同一个父节点的左右结点
        self.connectTwo(node2.left, node2.right)
        # 传入异父结点的左右结点
        self.connectTwo(node1.right, node2.left)
        return node1, node2

    def connect(self, root: 'Node') -> 'Node':
        if root is None:
            return root
        root.left, root.right = self.connectTwo(root.left, root.right)
        return root

使用递归方法思路简单,但是空间效率和时间效率都很低,所以接下来考虑一下非递归算法。

非递归算法

思路是这样的:观察最后的效果可以发现,是将每一层的结点相连接,位于右边缘的结点连接 N o n e None None,所以这样是不是能够使用层次遍历来实现呢?层次遍历就使用队列来实现,但是容易发现又遇到一个问题,对于队列中的若干节点如何判断哪些节点是同一层呢?我的方法是,将每一层入队列之后,插入一个 N o n e None None,这样就实现了层与层之间的分隔,这样需要初始化一个队列 [ r o o t , N o n e ] [root, None] [root,None],但是这是特殊情况,对于空树和只有一层的树来说不满足这样的情况,所以特殊考虑。循环里将队列的第一个元素和第二个元素相连,如果第一个元素是 N o n e None None,说明这一层结束了,而且下一层已经全部在队列中,所以需要 p o p pop pop第一个元素,然后 a p p e n d ( N o n e ) append(None) append(None)实现层的分隔。这样基本上完成了整个思路,但是还有一个问题,如果是最后一层的最后一个元素,遇到 N o n e None None之后 a p p e n d ( N o n e ) append(None) append(None),然后接着还是 N o n e None None,这样造成了无限循环,所以需要判断当前的结点是不是最后一层的最后一个结点,即:

layer[1] is None and layer[0].left is None

其实这个条件可以在 w h i l e while while循环里判断,即将

while layer != []

换为

while layer[1] is not None or layer[0].left is not None

class Solution:
    def connect(self, root: 'Node') -> 'Node':
        if root is None or root.left is None:
            return root
        else:
            layer = [root, None]
            # count = 1
            while layer != []:
                if layer[0] is not None:
                    layer[0].next = layer[1]
                    if layer[1] is None and layer[0].left is None:  # 判断是否为最后一层最后一个结点
                        break
                    layer.append(layer[0].left)
                    layer.append(layer[0].right)
                    layer.pop(0)
                else:
                    layer.pop(0)
                    layer.append(None)
                # cout += 1
            return root

第三种思路

使用:
node.left.next = node.next.left来实现异父相邻结点的连接。

class Solution:
    def connect(self, root: 'Node') -> 'Node':
        if not root:
            return None
        first = root
        while first.left:
            node = first
            while node:
                node.left.next = node.right
                if node.next:
                    node.right.next = node.next.left
                node = node.next
            first = first.left
        return root

猜你喜欢

转载自blog.csdn.net/weixin_43141320/article/details/113799088
今日推荐