题目描述
题目链接:116 117
116和117题目类似,都是要填充每个结点的 next 指针,让这个指针指向其下一个右侧节点。如果找不到下一个右侧节点,则将 next 指针设置为 NULL。(初始状态下,所有 next 指针都被设置为 NULL。)
例:
所不同的是116为完美二叉树,而117为普通二叉树。
解题思路
刚看题目描述,肯定是不太清楚是什么意思。其实就是二叉树的每个结点定义时就有一个next指针,我们所需要做的就是改变next指针的指向。
比如116题的完美二叉树的定义:
// Definition for a Node.
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) {}
};
完美二叉树
抓住两点。
- 一个结点的左孩子的 next 指针指向该结点的右孩子。
- 一个结点的右孩子的 next 指针指向该结点的 next 结点的左孩子。
root->left->next=root->right;
if(root->next) //判断条件要有
root->right->next=root->next->left;
二叉树
摘自:C++ O(1)空间 简洁 递归
与完美二叉树不同的是,可能一个结点没有孩子,可能有一个孩子。
对于任意一次递归,只考虑如何设置子节点的 next 属性,分为三种情况:
- 没有子节点:直接返回
- 有一个子节点:将这个子节点的 next 属性设置为同层的下一个节点,即为 root.next 的最左边的一个节点,如果 root.next 没有子节点,则考虑 root.next.next,依次类推
- 有两个节点:左子节点指向右子节点,然后右子节点同第二种情况的做法
注意递归的顺序需要从右到左
。我的理解:因为在这段代码的时候是从左到右寻找满足条件的结点,所以递归时要从右到左完成了结点的next指针后才能继续寻找。
while(nextnode&&!nextnode->left&&!nextnode->right)
nextnode=nextnode->next;
代码
完美二叉树
class Solution {
public:
Node* connect(Node* root) {
if(!root||!root->left) return root;//root->left为空表示是叶子结点
root->left->next=root->right;
if(root->next) //判断条件要有
root->right->next=root->next->left;
connect(root->left);
connect(root->right);
return root;
}
};
二叉树
class Solution {
public:
Node* connect(Node* root) {
if(!root||(!root->left&&!root->right)) return root;//空的,注意‘ !’
if(root->left&&root->right)root->left->next=root->right;//root有两个结点
//root有一个结点
Node* child=root->right? root->right:root->left;
Node* nextnode= root->next;
//找到root的右边节点中第一个有子节点的那个节点
while(nextnode&&!nextnode->left&&!nextnode->right)//这句话的意思:nextnode不为空且没有孩子 那么我就得继续寻找结点
nextnode=nextnode->next;
child->next=nextnode?(nextnode->left?nextnode->left:nextnode->right):NULL;
//必须保证右边节点的next已经被操作过,因此是从右子树到左子树的前序遍历
connect(root->right);
connect(root->left);
return root;
}
};