您的位置:首页 > Web前端 > Node.js

leetcode 116. Populating Next Right Pointers in Each Node-递归|非递归

2016-05-28 09:48 781 查看
原题链接:116. Populating Next Right Pointers in Each Node
【思路-Java、Python】

由于题目要求不能申请额外空间,并且已经说明给定的树为完全二叉树。

public class Solution {
public void connect(TreeLinkNode root) {
if (root == null) return;
TreeLinkNode nextLevelFirst = null;
while (root.left != null) {  //当前节点的左子树为空的完全二叉树意味着下一层没有节点
nextLevelFirst = root.left;
while (root != null) {
root.left.next = root.right;  //连接父节点的左右孩子
root.right.next = root.next==null ? null : root.next.left;  //连接堂兄弟的左右节点
root = root.next;
}
root = nextLevelFirst;
}
}
}
14 / 14 test
cases passed. Runtime: 0 ms  Your runtime beats 81.40% of javasubmissions.

class Solution(object):
def connect(self, root):
"""
:type root: TreeLinkNode
:rtype: nothing
"""
if not root : return
nextLevelFirst = root
while root.left :
nextLevelFirst = root.left
while root :
root.left.next = root.right
if root.next != None: root.right.next = root.next.left
root = root.next
root = nextLevelFirst
14 / 14 test
cases passed. Runtime: 101 ms  Your runtime beats 35.38% of pythonsubmissions.

【思路2-Java、Python】-递归实现

递归实现空间复杂度肯定是不符合要求的,但是,为了扩展视野,既懂递归实现又懂非递归实现,可以很好地帮助我们理解两者的区别,实际编程中可以游刃有余:

1. 既然非递归寻找下一层的第一个节点需要用到 nextLevelFirst,那么我们同样地在形参中增加一个 nextLevelFirst 参数。

2. 非递归实现的终止条件是 nextLevelFirst 为空,那么递归实现的终止条件也是 nextLevelFirst 为空

3. 非递归的 next 节点为空时,进行下一层的遍历,那么递归实现进行下一层遍历的条件也是 root.next 为空。同时更新 nextLeftFirst 引用

从上面几点,我们可以看到递归和非递归是高度统一的:

public class Solution {
public void connect(TreeLinkNode root) {
if (root != null)
dfs(root, root.left);
}
private void dfs(TreeLinkNode root, TreeLinkNode nextLevelFirst) {
if (nextLevelFirst == null) return;
root.left.next = root.right;
if (root.next == null) {
dfs(nextLevelFirst, nextLevelFirst.left);
} else {
root.right.next = root.next.left;
dfs(root.next, nextLevelFirst);
}
}
}
14 / 14 test
cases passed. Runtime: 1 ms  Your runtime beats 29.25% of javasubmissions.

class Solution(object):
def connect(self, root):
if not (root and root.left):
return

root.left.next = root.right
if root.next:
root.right.next = root.next.left

map(self.connect, (root.left, root.right))
14 / 14 test
cases passed. Runtime: 104 ms  Your runtime beats 23.10% of pythonsubmissions.

【思路3-Java】-仅供参考,不推荐

如果没有仔细思考,没有利用到 next 指针,我们可能很快就想到利用队列实现二叉树的层次遍历,但这样与思路1相比不仅造成空间浪费,而且时间复杂度更高:

public class Solution {
public void connect(TreeLinkNode root) {
if (root == null) return;
Queue<TreeLinkNode> queue = new LinkedList<TreeLinkNode>();
queue.add(root);
queue.add(null);     //将null加入该层的结尾,作为该层的结束标志
TreeLinkNode temp = root;
while (!queue.isEmpty()) {
if (root != null) {         //本层还未遍历完
if (root.left != null)  //将左孩子加入队列,作为下一层节点
queue.add(root.left);
if (root.right != null)  //将右孩子加入队列,作为下一层节点
queue.add(root.right);
} else {                   //本层遍历完成,开始遍历下一层
queue.add(null);       //加入null作为本层结束的标志
root = queue.poll();
temp = root;
continue;
}
root = queue.poll();      //取出本层的下一个节点
temp.next = root;         //设置next指针
temp = root;
}
}
}
14 / 14 test
cases passed. Runtime: 8 ms  Your runtime beats 2.81% of javasubmissions.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Java Python leetcode