Leetcode 117 Populating Next Right Pointers in Each Node II 二叉树填充next指针指向右侧结点 II
2015-07-01 16:36
831 查看
原题地址
https://leetcode.com/problems/populating-next-right-pointers-in-each-node-ii/题目描述
Follow up for problem “Populating Next Right Pointers in Each Node”.116题树填充next指针指向右侧结点的的延伸。
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 perfect 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
解题思路
116题的解题过程请见Leetcode 116 Populating Next Right Pointers in Each Node 树填充next指针指向右侧结点116题是117题一个特例,特殊在树的结构上。116题中树是一个完全树,在那种特殊情况下我们可以很轻松的找到一个递归解决方案。然而对于任意一棵树,那样的方案是行不通的。
经过观察和思考,我大概想到了三种可能的方案。
方案一
使用额外空间,用队列什么的。然而题目要求只能使用常数级的额外空间。所以此方案不可。方案二
依然按照116题相似的思路。即:对于某一个树的根结点来说,将其左右子树的每一层的边界结点连接起来,然后递归处理左右子树。这个过程大概看起来是这样子的:procedure connect(root)
for every level l of root
—-find rightest node leftNode in level l of root->left
—-find leftest node rightNode in level l of root->right
—-leftNode->next = rightNode
end for
call connect(root->left)
call connect(root->right)
在上述过程中,较116题中有所变化的是找到某一层的边界结点的过程。由于116题中树结构的特殊性,找到边界点的过程比较简单,然而对于任意一个树来说,这个过程就变得比较麻烦了。因此次方案不是不可行,也符合使用常数级的额外空间的要求,但是时间复杂度过高。
实际上,我一开始实现了这种解决方案,但是此处就不具体描述了,有兴趣的可以看一下代码。
方案三
第三种方案还是挺好理解的。请看如下解释。我们按层序来处理树。假设我们有如下一棵树: 1 / \ 2 3 / \ \ 4 5 6 / / \ \ 7 8 9 10 \ / 11 12 / 13 (1)假设某一时间点上,我们已经处理好了前3层,如下: 1->null / \ 2-> 3->null / \ \ 4-> 5-> 6->null <--- 第3层以前已经处理好了 / / \ \ 7 8 9 10 <--- 接下来要处理第4层 \ / 11 12 / 13 (2)我们可以发现,要处理第四层的各个结点,我们可以根据第三层这条横着的链表来处理。为了方便处理,我们把第三层和第四层拆出来处理。 4-> 5-> 6->null / / \ \ 7 8 9 10 使用两个指针pre和next分别指向第四层中的两个结点,目的是要把pre->next和next连接起来。 我们从第3层的最左侧结点开始往右前进(设为p),然后根据p的左右孩子情况来更新pre和next的指向。过程如下: (3)初始情况下: p ↓ 4-> 5-> 6->null / / \ \ 7 8 9 10 ↑ pre (4)找到下一个next p ↓ 4-> 5-> 6->null / / \ \ 7 8 9 10 ↑ ↑ pre next (5)连接pre和next p ↓ 4-> 5-> 6->null / / \ \ 7-> 8 9 10 ↑ ↑ pre next (6)移动p、pre和next,并连接 p ↓ 4-> 5-> 6->null / / \ \ 7-> 8-> 9 10 ↑ ↑ pre next (7)移动p、pre和next,并连接 p ↓ 4-> 5-> 6->null / / \ \ 7-> 8-> 9->10->null ↑ ↑ pre next 这样,我们处理好第四层之后,可以再根据第四层横向的单链表来处理第五层,直至所有层都处理结束。
这种方案满足使用常数级额外空间的要求,空间复杂度O(c);同时也是one-pass,时间复杂度O(n)。
代码
/** * 填充树的next指针 * input root : 树某一层的最左侧结点 */ void connect(struct TreeLinkNode *root) { if (root == NULL) return; struct TreeLinkNode *begin = NULL, *upperNode = root, *pre; /* 找到当前层的第一个结点 */ while (upperNode != NULL) { if (upperNode->left != NULL) { begin = upperNode->left; break; } else if (upperNode->right != NULL) { begin = upperNode->right; break; } else upperNode = upperNode->next; } /* 当前层没有任何结点,直接返回 */ if (begin == NULL) return; /* 为了方便统一处理,判断是否需要处理当前upperNode指向的结点 */ pre = begin; if (begin == upperNode->left && upperNode->right != NULL) { pre->next = upperNode ->right; pre = pre->next; } upperNode = upperNode->next; // upperNode指向下一个结点 /* 处理上一层中剩余的所有结点 */ while ( upperNode != NULL) { if(upperNode->left != NULL) { // 如果结点的left不为空,则连接 pre->next = upperNode->left; pre = pre->next; } if (upperNode->right != NULL) { // 如果结点的right不为空,则连接 pre->next = upperNode->right; pre = pre->next; } upperNode = upperNode->next; // upperNode指向下一个结点 } /* 递归处理下一层 */ connect(begin); }
完整代码 https://github.com/Orange1991/leetcode/blob/master/117/c/solution2.c
运行结果
Lauguage Status Time Comment c Accept 48ms Violence c Accept 8ms cpp Accept 40ms
2015/7/1
相关文章推荐
- sigaction函数中 SA_NODEFER与sa_mask之间
- Leetcode 116 Populating Next Right Pointers in Each Node 二叉树填充next指针指向右侧结点
- 《转》 Openstack Grizzly 指定 compute node 创建 instance
- hadoop系列 第一坑: hdfs JournalNode Sync Status
- 【nodejs】 npm 注意事项
- leetcode - Remove Nth Node From End of List
- nodejs入门(一)
- 动态修改 NodeJS 程序中的变量值
- ENode框架Conference案例分析系列之 - ENode框架初始化
- 学习老外用webstorm开发nodejs的技巧--代码提示DefinitelyTyped
- 学习老外用webstorm开发nodejs的技巧--代码提示DefinitelyTyped
- 学习老外用webstorm开发nodejs的技巧--代码提示DefinitelyTyped
- 学习老外用webstorm开发nodejs的技巧--代码提示DefinitelyTyped
- nodejs经验
- 【LeetCode】Remove Nth Node From End of List
- nodejs Crypto使用
- node.js安装、使用
- 【nodejs】 文件系统(fs) 之读写文件
- java.io.FileNotFoundException: /home/hadoop/hadoop/dfs/namenode/current/VERSION (Permission denied)
- 【nodejs】关于 alert 和 document