先看116
Given a binary tree
struct Node {
int val;
Node *left;
Node *right;
Node *next;
}
Populate each next pointer to point to its next right node. If there is no next right node, the next pointer should be set to NULL.
Initially, all next pointers are set to NULL.
method 1 层次遍历
显然本题可归为层序遍历的问题,直接套用层序遍历的模板稍加修改即可
Node* connect(Node* root) {
queue<Node*> q;q.push(root);q.push(NULL);while (q.size() > 1){
Node* p = q.front(); while (p != NULL){
if (p->left) q.push(p->left);if (p->right) q.push(p->right);q.pop();Node* next = q.front();if (next == NULL) break;p->next = next;p = next;}q.pop();q.push(NULL);}return root;
}
method 2
但本题在不考虑递归栈的空间情况,是有O(1) space的算法
还是层序遍历的思想,但通过思考可以发现,当上一层的next指针连接好时,可以通过上一层的遍历连接本层的结点
void connect(Node *root) {
if (!root)return;while (root->left){
Node *p = root;while (p){
p->left->next = p->right;if (p->next)p->right->next = p->next->left;p = p->next;}root = root->left;}
}
summary
- 把树的问题归纳为遍历顺序的问题
- 这种递归问题的范式:当处理第n层时,有助于处理第n+1层,并且一般一开始的情况很好处理,有点像动态规划
进一步,看117题,
所给的条件不再是一颗perfect tree,增加了难度
同样地,可以套用层序的模板
但是想达到O(1) space,那么必须在连接第n层的时候,记录第n+1层的第一个结点,在116问题中所给的是一颗完全二叉树,所以这不是一个问题,但在117中这并不确定,因此可以引入dummyNode,当遍历第n层结点时,指示第n+1层的第一个结点
dummyNode的概念:https://blog.csdn.net/skyline_sun/article/details/81275746
class Solution {
public:Node* connect(Node* root) {
if (!root) return root;Node* ans = root;Node* dummyNode = new Node(0);while (root){
Node* cur = dummyNode;while (root){
if (root->left){
cur->next = root->left; cur = cur->next;}if (root->right){
cur->next = root->right; cur = cur->next;}root = root->next;}root = dummyNode->next;dummyNode->next = NULL;}return ans;}
};
dummyNode->next = NULL; 的作用在于,当遍历树的最后一行,防止外部的循环无限循环
summary
- 把树的问题归纳为遍历顺序的问题
- 引入dummyNode指示第一个结点!在链表问题中避免第一个结点的多余操作,还可以指示第一个结点
- trick : 为什么dummyNode会指示下一层的第一个结点,因为又另外声明了一个cur结点,让cur结点进行层序遍历,并提前将dummyNode赋值给cur,在cur结点遍历的时候,会自然遍历到第一个结点,此时dummyNode指向第一个结点(通过赋值的办法,使一个指针得到头结点,并且不用随另一指针遍历而被改变)