leetcode两道题目地址:
完美二叉树版
填充每个节点的下一个右侧节点指针
数据类型:
class Node {
public:
int val;
Node* left;
Node* right;
Node* next;
Node() : val(0), left(NULL), right(NULL), next(NULL) {
}
Node(int _val) : val(_val), left(NULL), right(NULL), next(NULL) {
}
Node(int _val, Node* _left, Node* _right, Node* _next)
: val(_val), left(_left), right(_right), next(_next) {
}
};
一、层次遍历
使用层次遍历(实质为BFS),遍历每一层然后不断赋值,思路简单明了。
两道题都可以。
class Solution {
public:
Node* connect(Node* root)
{
if (!root)
return NULL;
queue< Node*> q;
q.push(root);
while (!q.empty())
{
int n = q.size();
Node* node = NULL;
for (int i = 0; i < n; i++)
{
Node* f = q.front();
q.pop();
if (f->left!=NULL)
{
q.push(f->left);
}
if (f->right!=NULL)
{
q.push(f->right);
}
if (i != 0)
{
node->next = f;
}
node = f;
}
}
return root;
}
};
二、使用已有的next指针
因为必须处理树上的所有节点,所以无法降低时间复杂度,但是可以尝试降低空间复杂度。
不难发现:一旦在某层的节点之间建立了 next指针,那这层节点实际上形成了一个链表。因此,如果先去建立某一层的 next 指针,再去遍历这一层,就无需再使用队列了。
对于完美二叉树:
节点一定完整,不存在一个父节点只有一个子节点的情况。
class Solution {
public:
Node* connect(Node* root)
{
Node* head = root;
if (!head)
return NULL;
while (head->left!=nullptr)
{
Node* center = head;
while (center)
{
center->left->next = center->right;
if (center->next)
center->right->next = center->next->left;
center = center->next;
}
head = head->left;
}
return root;
}
};
非完美二叉树
会出现一个父节点没有子节点或者只有一个的情况。
就需要记录前一位指针,和下一层的起始位置。
class Solution {
public:
void handle(Node*& last, Node*& p, Node*& nextStart) {
//前一位指针,当前连接的指针p,下层的首部节点nextstart
if (last)
last->next = p;
if (!nextStart) //为空则等于p
nextStart = p;
last = p;
}
Node* connect(Node* root)
{
if (!root)
{
return nullptr;
}
Node* start = root;
while (start)
{
Node* last = nullptr, * nextStart = nullptr;
for (Node* p = start; p != nullptr; p = p->next)
{
//给下一层建立next指针
if (p->left)
handle(last, p->left, nextStart);
if (p->right)
handle(last, p->right, nextStart);
}
//最后一个nextstart则为下一层开始的起始指针
start = nextStart;
}
return root;
}
};