继续思考"填充每个节点指向最右节点的next指针" 这道题
如果给定的树可以是任意的二叉树呢?你之前的给出的算法还有效吗?
注意:
- 你只能使用常量的额外内存空间
例如:
给出的二叉树如下:
调用完你给出的函数之后,这棵树应该变成:
class Solution
{
public:
void connect(TreeLinkNode *root)
{
while(root)
{
TreeLinkNode dummy(-1), *prev;
prev = &dummy;
for(auto p = root; p; p = p->next)
{
if(p->left)
{
prev->next = p->left;
prev = prev->next;
}
if(p->right)
{
prev->next = p->right;
prev = prev->next;
}
}
root = dummy.next; // 指向下一层的第一个节点
}
}
};
public void connect(TreeLinkNode root) {
while (root != null) {
//tmpLevelFirst为新建立的每层第一个节点(为了方便后面遍历当前行节点)
TreeLinkNode tmpLevelFirst = new TreeLinkNode(0);
TreeLinkNode cur = tmpLevelFirst;
while (root != null) {
if (root.left != null) {
cur.next = root.left;
cur = cur.next;
}
if (root.right != null) {
cur.next = root.right;
cur = cur.next;
}
root = root.next;
}
root = tmpLevelFirst.next;
}
} 看了下讨论区的代码,几乎都没达到常量内存空间的要求;
class Solution {
public:
void connect(TreeLinkNode *root) {
TreeLinkNode*cur = root;
TreeLinkNode*pre;
int count = 1;
while (cur){
bool flag = true;
for (auto p = cur; p; p = p->next){
if (p->left){
if (flag){
cur = p->left;
flag = false;
pre = p->left;
}
else{
pre->next = p->left;
pre = pre->next;
}
}
if (p->right){
if (flag){//第一次进入该层
cur = p->right;
flag = false;
pre = p->right;
}
else{
pre->next = p->right;
pre = pre->next;
}
}
}
if (flag)//如果没进入for循环说明cur已经是最后一层
return;
}
}
};
class Solution {
public:
void connect(TreeLinkNode *root) {
//利用层序遍历思想,需要注意的是对每层的节点都进行处理
if(root==NULL) return;
queue<TreeLinkNode*> que;
que.push(root);
while(!que.empty()){
int n=que.size();
for(int i=0;i<n;i++){
TreeLinkNode* tmp=que.front();
que.pop();
if(tmp->left) que.push(tmp->left);
if(tmp->right) que.push(tmp->right);
if(i!=n-1) tmp->next=que.front();
else tmp->next=NULL;
}
}
}
};
这个问题我们可以通过二叉树的层序遍历进行解决,需要注意的是,对每一层的节点进行对应的层序遍历!
所以告诉我为什么问题一和问题二我用同一份代码就都过了。。。
import java.util.LinkedList;
import java.util.Queue;
public class Solution {
public void connect(TreeLinkNode root) {
if(root == null)
return;
Queue<TreeLinkNode> queue = new LinkedList<>();
queue.offer(root);
while(!queue.isEmpty()){
int len = queue.size();
for(int i = 0; i < len; i++){
TreeLinkNode tmp = queue.poll();
if(i == len - 1){
tmp.next = null;
}else {
tmp.next = queue.peek();
}
if(tmp.left != null)
queue.offer(tmp.left);
if(tmp.right != null)
queue.offer(tmp.right);
}
}
}
}
import java.util.*;
// 层次遍历,记录每一层的结点个数,循环设置next指针
public void connect(TreeLinkNode root) {
if(root == null) return;
Queue<TreeLinkNode> queue = new LinkedList<>();
queue.add(root);
int curCount = 1;
int nextCount = 0;
while ( ! queue.isEmpty()) {
TreeLinkNode[] arr = new TreeLinkNode[curCount]; // 存放一层结点
for (int i = 0; i < curCount; i ++) {
TreeLinkNode curNode = queue.poll();
arr[i] = curNode;
if(curNode.left != null) {
queue.add(curNode.left);
nextCount ++;
}
if(curNode.right != null) {
queue.add(curNode.right);
nextCount ++;
}
}
for (int i = 0; i < arr.length - 1; i ++) {
arr[i].next = arr[i + 1];
}
curCount = nextCount;
nextCount = 0;
}
}
class Solution {
public:
void connect(TreeLinkNode *root) {
if(root == NULL)
return;
//层次遍历
queue<TreeLinkNode*> q;
q.push(root);
TreeLinkNode* curNode = NULL;
TreeLinkNode* nextNode = NULL;
while(! q.empty()){
//和一般的层次遍历略有不同,每次while要把当前层的节点全部弹出去
int len = q.size();
curNode = q.front();
q.pop();
if(curNode->left != NULL)
q.push(curNode->left);
if(curNode->right != NULL)
q.push(curNode->right);
for(int i = 1;i<len;++i){
nextNode = q.front();
q.pop();
curNode->next = nextNode;
curNode = nextNode;
if(curNode->left != NULL)
q.push(curNode->left);
if(curNode->right != NULL)
q.push(curNode->right);
}
curNode->next = NULL;
}
}
};
// Two Solutions
class Solution {
public:
// DFS
void connect(TreeLinkNode* root) {
int max_depth = -1;
vector<TreeLinkNode*> nexts;
function<void(TreeLinkNode*, int)> DFS =
[&](TreeLinkNode* r, int d) -> void {
if (!r) return;
if (d > max_depth) {
nexts.emplace_back(r);
max_depth = d;
} else {
r->next = nexts[d];
nexts[d] = r;
}
DFS(r->right, d + 1);
DFS(r->left, d + 1);
};
DFS(root, 0);
}
// BFS
void connectII(TreeLinkNode *root) {
// corner case
if (!root) return;
queue<TreeLinkNode*> q{{root}};
while (not q.empty()) {
size_t s = q.size();
TreeLinkNode* pre = nullptr;
while (s--) {
auto curr = q.front(); q.pop();
if (pre) pre->next = curr;
if (curr->left) q.emplace(curr->left);
if (curr->right) q.emplace(curr->right);
pre = curr;
}
}
}
}; /**
* Definition for binary tree with next pointer.
* public class TreeLinkNode {
* int val;
* TreeLinkNode left, right, next;
* TreeLinkNode(int x) { val = x; }
* }
*/
public class Solution {
public void connect(TreeLinkNode root) {
while(root != null){
TreeLinkNode dummy = new TreeLinkNode(0);
TreeLinkNode cur = dummy;
while(root != null){
if(root.left != null){
cur.next = root.left;
cur = cur.next;
}
if(root.right != null){
cur.next = root.right;
cur = cur.next;
}
root = root.next;
}
root = dummy.next;
}
}
} /**
* Definition for binary tree with next pointer.
* public class TreeLinkNode {
* int val;
* TreeLinkNode left, right, next;
* TreeLinkNode(int x) { val = x; }
* }
*/
public class Solution {
public TreeLinkNode connect(TreeLinkNode root) {
TreeLinkNode head = root;
while(head!=null){
// 递归构造每一层的链表:从最左边元素连到最右边元素
// 当前节点是当前层的最左边节点,返回的是子节点一层的最左边节点
head = findNext(head, head.next);
}
return root;
}
// 子节点的最右边元素,是父节点的右边元素的子节点的最左边元素
// 返回当前节点子节点的最左边元素
public TreeLinkNode findNext(TreeLinkNode node, TreeLinkNode pNext){
TreeLinkNode next = null;
if(pNext!=null) {
next = findNext(pNext, pNext.next);
}
if(node.right!=null){
node.right.next = next;
next = node.right;
}
if(node.left!=null){
node.left.next = next;
next = node.left;
}
return next;
}
} class Solution {
public:
void connect(TreeLinkNode *root) {
if(!root)return;
queue<TreeLinkNode*>que;
que.push(root);
while(!que.empty()){
int len=que.size();
for(int i=0;i<len;i++){
TreeLinkNode* cur=que.front();
que.pop();
if(i!=len-1)
cur->next=que.front();
if(cur->left)que.push(cur->left);
if(cur->right)que.push(cur->right);
}
}
}
}; 和上一题基本上一样。
唯一的区别就是每一层的节点数不一样了。
把下一层的节点数统计出来。每次往队列中添加节点时,把计数器加一即可。
public class Solution {
public void connect(TreeLinkNode root) {
if (root == null) return;
int n = 1; //这一行的个数。
int row = 0; //行号。
int loc = 0; //当前位置。
int next = 0;
TreeLinkNode pre = null; //前一个节点。
Stack<TreeLinkNode> stack = new Stack<>();
Queue<TreeLinkNode> queue = new LinkedList<>();
queue.offer(root);
while (!queue.isEmpty()) {
loc++;
TreeLinkNode node = queue.poll();
if (pre != null) pre.next = node;
if (node.left != null) {
queue.offer(node.left);
next++;
}
if (node.right != null) {
queue.offer(node.right);
next++;
}
if (loc == n) {
node.next = null;
row++;
n = next;
next = 0;
loc = 0;
pre = null;
} else {
pre = node;
}
}
}
}
//常量空间 三个指针
class Solution {
public:
void connect(TreeLinkNode *root) {
TreeLinkNode *p = NULL, *cur = NULL, *f = root;
while(f){
p = f;
cur = NULL;
while(!cur && p){
if(p -> right && p -> left) {p -> left -> next = p -> right; cur = p -> right;}
else if(p -> left) cur = p -> left;
else if(p -> right) cur = p -> right;
p = p -> next;
}
while(p){
if(p -> right && p -> left) {
cur -> next = p -> left;
p -> left -> next = p -> right;
cur = p -> right;
}
else if(p -> left) {cur -> next = p -> left; cur = p -> left;}
else if(p -> right) {cur -> next = p -> right; cur = p -> right;}
p = p -> next;
}
while(f){
if(f -> left) {f = f -> left; break;}
else if (f -> right) {f = f -> right; break;}
f = f -> next;
}
}
return ;
}
}; class Solution {
public:
void connect(TreeLinkNode *root) {
if(root == NULL)
{
return ;
}
TreeLinkNode *node1,*node2;
queue<TreeLinkNode*> que;
que.push(root);
int count = 0;
while(!que.empty())
{
count = que.size();
node1=que.front();
que.pop();
if(node1->left != NULL)
que.push(node1->left);
if(node1->right != NULL)
{
que.push(node1->right);
}
count--;
while(count-- > 0)
{
node2 = que.front();
que.pop();
if(node2->left != NULL)
que.push(node2->left);
if(node2->right != NULL)
que.push(node2->right);
node1->next = node2;
node1 = node2;
}
node1->next = NULL;
}
}
};
//类似BFS的思想
class Solution {
public:
void connect(TreeLinkNode *root) {
while(root){
TreeLinkNode dummy(-1),*pre=&dummy;
while(root){
if(root->left) pre->next=root->left,pre=pre->next;
if(root->right) pre->next=root->right,pre=pre->next;
root=root->next;
}
root=dummy.next;
}
}
}; class Solution {
public:
void connect(TreeLinkNode *root) {
while(root)
{
TreeLinkNode L(-1),*f,*p;
f = &L;
p = root;
while(p)
{
if(p->left != NULL)
{
f->next = p->left;
f = f->next;
}
if(p->right != NULL)
{
f->next = p->right;
f = f->next;
}
p = p->next;
}
root = L.next;
}
}
};