经过这道题,我明白了一个道理:在具备基础知识的条件下,做不出来题往往是被自己的惯性思维局限住了。
题目描述
看到这里,我一开始蒙了。本来按层序遍历,直接拿个队列广度搜索就能够解决这道题,然而要求常量级空间,这意味着我几乎无法使用任何数据结构进行辅助。那还层序遍历个鬼?
然后我又看到了,使用递归解题符合要求?递归解题?那就是要我遍历这个树吧?广度搜索不行,那就深度搜索吧。先序中序后序挑哪个呢?
于是我进坑了,下面思路 1 就是我进坑的情况:
思路 1
写的很杂乱,可以看到我把深度搜索的每种序列都写了出来,企图找出一些规律。然后我选择了后序遍历,并且决定维护一个标记变量 left。它的作用,主要是处理一些跨树节点的链接。举例来说:
对于 8 和 9 的链接很简单,没有必要担心,需要处理的是,如何链接 8 和 10。因为对于后序遍历:8,9,4,10,11...
,在 8 和 10 之间夹了一个非同层节点 4。通过标记变量,我会先暂时记住这个非同层节点,等到下次遍历到 5 时,将它和 4 相连即可。
这个方法对于一个三层的树或许行得通,但是对于一个 4 层,5 层甚至更多的层的树,单一一个标记节点就不够了。原因在于,此时这种跨树的需要记忆的节点最多为layer - 2
个。
这种方法不行,那我只能推翻了,从新在纸上画画。然后灵光一现,我为什么一定要遍历呢?
其实难点就只是处理跨树节点,那我直接由上到下,将树劈成左右两边,然后把沿着裂痕拼起来不就行了。
于是有了思路 2
思路 2
思路就是先劈大树,再劈枝丫。想清楚了就太简单了,上代码:
public class Solution1 {
public Node connect(Node root) {
if (root == null) return null;
Node lTree = root.left;
Node rTree = root.right;
while (lTree != null && rTree != null) {
lTree.next = rTree;
lTree = lTree.right;
rTree = rTree.left;
}
connect(root.left);
connect(root.right);
return root;
}
}