每种方法都有详细注解,第三种【使用已建立的next指针】我写了非常详细的题解,俺觉得应该是看完就能懂的。
温馨提示:可以先画个树然后跟着我模拟,应该会非常清晰
法一、递归
时间复杂度O(n),空间复杂度O(logn)
Node* connect(Node* root) {
if (root == nullptr || root->left == nullptr) return root;
//当root为叶子结点时root->left不存在,就不需要往下给它们连了
//连接1、将root的左右子相连
root->left->next = root->right;
//连接2、将root的右子与root->next的左子相连
if (root->next) root->right->next = root->next->left;//只有当root为该层最后一个结点时root->next才==nullptr
if (root->left) connect(root->left);
if (root->right) connect(root->right);
}
法二、BFS 层次遍历 + 队列
时间复杂度O(n),空间复杂度O(n)
跟着下面代码模拟…比如当size=que.size()=4时,此时队列中元素为[4,5,6,7],进入内层循环。第一次内层循环进入后size–变为3,p=front=4, 4->next=5, 由于4没有孩子因此直接进入下一循环···直到最后一次内层循环进入后size–变为0,队列元素为[7],p=front=7弹出, 因为size=0遍历到了该层的最后一个结点了,不用再将7与谁连接了。
Node* connect(Node* root) {
queue<Node*> que;
if (root != nullptr) que.push(root);
while (!que.empty()){//外层的while迭代的是层数
int size = que.size();
// int upperlevel = size;
while (size--) {//遍历整层结点
//取出队首结点--上一层的结点
Node* p = que.front();
que.pop();
//连接
if (size > 0) p->next = que.front();
//除了最后一次内层循环,也就是执行完size--后size=0,遍历到上一层的最后一个结点,
//由于最后一个结点后面没有结点了,因此不需要将最后一个结点与谁连接起来
//拓展下一层结点
if (p->left) que.push(p->left);
if (p->right) que.push(p->right);
}
}
}
法三、使用已建立的next指针
时间复杂度O(n),空间复杂度O(1)
一、连接的两种情况
(1)连接同一父节点的两个子节点,它们可以通过该父节点直接连接到一起【cur->left->next = cur->right;】
(2)连接(cur的右子)与(cur->next的左子),可以通过cur与cur->next之间已建立的next指针进行连接.【cur->right->next = cur->next->left;】
简言之,连接涉及两层 => 遍历第i层的结点时给第i+1层的结点做连接:
遍历到第i层的结点cur时,需要
(1)连接cur的左右子结点;
(2)连接cur->right与cur->next->left.
每完成一个cur的连接就要更新cur–右移【cur=cur->next】,直到遍历完第i层的最后一个结点时cur->next==nullptr该层遍历结束,第i+1层的结点之间都已建立好了next。
(但是注意当cur遍历到第i层的最后一个结点时不需要做第二步连接,因为cur->next==nullptr, cur->right已经是第i+1层的最后一个结点)
第i层遍历完成之后要遍历下一层了,也就要从下一层(第i+1层)的第一个结点(leftmost)开始遍历,给第i+2层的结点做连接,那么怎么才能找到下一层的第一个结点呢?
————刚开始第i层遍历前的cur不就是第i层的第一个结点吗?则此时cur的左子就是第i+1层的第一个结点。因此只需要在该层遍历之前保存cur的初始值leftmost,则leftmost->left就是下一层的第一个结点,遍历完该层再将cur更新即可.
Node* connect(Node* root) {
if (root == nullptr) return root;
Node* leftmost = root;//leftmost:每一层的最左结点
Node * cur = root;//用于遍历一层结点
//直接用root遍历则会改变root
while (leftmost->left != nullptr) {//外层while迭代的是层数
//若leftmost->left == nullptr说明leftmostcur是叶子节点,则不需要继续连接了
leftmost = leftmost->left;//保存下一层的第一个结点
while (cur) {//内层的while迭代的是层中结点
//用cur遍历第i层的每一个结点,通过左右指针以及该层已建立的next连接第i+1层的结点
cur->left->next = cur->right;//连接(1)
if (cur->next != nullptr) {
cur->right->next = cur->next->left;//连接(2)
cur = cur->next;//处理下一个结点
}
else break;//直到cur->next==nullptr该层遍历结束
}
cur = leftmost;//一层遍历结束,更新cur
}
return root;
}
呼,写题解花了我挺长时间的,如果有帮助的话可以评论区告诉我给我激励一下bro~