题目
提示:
- 你只能使用常量级额外空间。
- 使用递归解题也符合要求,本题中递归程序占用的栈空间不算做额外的空间复杂度。
思路
这一道题目很容易审题错误,像我,我就依据上面的那张图,认定只要让一个节点 左孩子连上右孩子, 让左孩子的右孩子 连上 右孩子的左孩子 就可以了。
然而它给我们展示的图片是没有包含所有情况的,例如下边这种情况:
二叉树的层数非常多的时候,就会碰到麻烦。
上面的 11 和 12 使用一般方法无法连接上
还有,如果两个节点中间有几个空的节点(不好意思,搞错了!!!,题目没看清,每一个父节点都有两个子节点。哎哟!)
但是还是留在这里,当作个审题眼睛没看清的记号吧。
层次遍历法(使用队列)
其实总容易想到的就是层序遍历了,只要将每一层的节点存入队列中。
然后,每一次取出每一层的数据,进行连接,特别方便。但是题目要求不允许这样使用:
/*
先试用队列来做吧
*/
class Solution {
public Node connect(Node root) {
if(root == null) return null;
Queue<Node> queue = new LinkedList<Node>();
queue.offer(root);
Node prev;
while(!queue.isEmpty()){
prev = null;
int size = queue.size();
while(size-->0){
Node node = queue.poll();
// 让右边先入队列,这样左边出队列的时候,它的 prev就是右边(右边先出队列),可以直接 left.next = prev(right)
if(node.right != null) queue.offer(node.right);
if(node.left != null) queue.offer(node.left);
node.next = prev;
prev = node;
}
}
return root;
}
}
这样的空间复杂度不满足题目要求(常数级)
层次遍历法(使用递归)
因此,使用一下层次遍历的递归,这样就不用创建一个队列了
/*
DFS,先递归到最右,然后让这个 node指向 prev(prev=null),然后让prev==null。
第一次递归到该层的时候,往 levels添加元素,之后每一层对应的节点从 levels根据 level下标取出,
上一次存入的 prev,用 next指向它之后,将自己赋值为 prev
*/
class Solution {
List<Node> levels = new ArrayList<Node>();
public Node connect(Node root) {
connect(root, 0);
return root;
}
public void connect(Node root, int level){
if(root == null) return;
if(level >= levels.size()){
// 每一层第一次进入的时候,初始化每一层为 null,
levels.add(null);
}
Node node = levels.get(level);
root.next = node;
levels.set(level, root);
connect(root.right, level+1);
connect(root.left, level+1);
}
}
空间复杂度应该是 O(H),H是二叉树的层数。依旧不满足常数级的要求
没辙了,那几个特殊情况太难解决了。只能求助题解区大佬了。
无敌是多么寂寞
class Solution {
// 这无敌的代码
public Node connect(Node root) {
dfs(root, null);
return root;
}
private void dfs(Node node, Node next) {
if(node != null) {
// 这一步是连接上一级别传入的,左右孩子
node.next = next;
// 这一步是让此节点的左右孩子,相互连接
dfs(node.left, node.right);
// 下面画图理解
dfs(node.right, node.next != null ? node.next.left : null);
}
}
}
画了图的话,还是比较容易做出来的