LeetCode 116, 117. Populating Next Right Pointers in Each Node I + II
116. Populating Next Right Pointers in Each Node
直接做的话用levelOrder做即可,但是要求空间复杂度O(1),所以不行。
Recursive
这里递归是preOrder,一定要先将root的左右儿子连接起来,后面递归才能继续连接。
这里每次dfs到root的时候是处理孩子,而不是将当前root和右边的node连接,是因为我们无法得到右边节点的信息(我们无法返回到当前root的parent)。先将左儿子和右儿子连接起来,然后连接右儿子和右边的节点(由于preOrder,root已经连接完毕,我们可以通过 root->next->left 找到右边的节点)。
class Solution { public: void connect(TreeLinkNode *root) { if (root==NULL) return; if (root->left){ // if root has two sons root->left->next = root->right; if (root->next!=NULL){ root->right->next = root->next->left; } } connect(root->left); connect(root->right); } };
如果不算递归所用栈的空间的话O(1)。
Non-recursive
思路和levelOrder一样,不同的是不借助queue。每次连接下一层的node,通过next遍历这一层的所有节点(这样下一层的节点就都连接好了)。root = root->left 到下一层继续。
class Solution { public: void connect(TreeLinkNode *root) { TreeLinkNode *cur; while (root!=NULL){ cur = root; while (cur!=NULL){ if (cur->left!=NULL){ cur->left->next = cur->right; if (cur->next){ cur->right->next = cur->next->left; } } cur = cur->next; } root = root->left; } } };
117. Populating Next Right Pointers in Each Node II
相比上一题缺少了perfect binary tree的限制,但是思路还是一样的。
Recursive (116-like)
前一题我们只要连接root->left和root->right,以及root->right和root->next->left。但是对于本题来说,需要连接的node有很多情况。这里我们引入一个helper function findNext(),找到需要连接的右边的节点。这个function也是递归的。
但是需要特别注意的是,这里我们要根右左,即最后先connect(root->right),再connect(root->left)。这是因为findNext函数可能会递归root->next->next ... ,如果右边此时没有处理好的话,就会报错。
2 / \ 1-> 3 / \ / \ 0->7->9 1 / / \ / \ 2-> 1->"0"8 8
如图所示,如果根左右,处理到“0”的时候,findNext(7) 会调用 findNext(9),导致错误发生。
class Solution { public: void connect(Node* root) { //修改成void if (root==NULL) return; if (root->left){ if (root->right) root->left->next = root->right; else root->left->next = findNext(root->next); } if (root->right){ root->right->next = findNext(root->next); } connect(root->right); connect(root->left); } Node *findNext(Node *root){ // find the next node in the same level if (root==NULL) return NULL; if (root->left) return root->left; if (root->right) return root->right; return findNext(root->next); } };
接下来的方法需要一个prev指针,用来连接。
Recursive (use prev)
Non-recursive
上一题的解法是连接root->left和root->right,以及root->right和root->next->left。由于next的节点不好找,我们可以用类似levelOrder遍历+prev来连接。进去下一个level我们可以用 root = dummy->next,因为dummy开始的这条链表就是连接好的下一层。
class Solution { public: void connect(Node* root) { while (root!=NULL){ Node *dummy=new Node(0,NULL,NULL,NULL), *prev=dummy, *cur=root; while (cur){ if (cur->left){ prev->next = cur->left; prev = cur->left; } if (cur->right){ prev->next = cur->right; prev = cur->right; } cur = cur->next; } root = dummy->next; } } };
Reference
Mostly-recursive-solution-O(n)-time-(beats-99.32)-and-O(1)-space-(without-considering-stack)
C++-recursive-solution-easy-understanding
not used

浙公网安备 33010602011771号