Medium!

题目描述:

给定一个二叉树

struct TreeLinkNode {
TreeLinkNode *left;
TreeLinkNode *right;
TreeLinkNode *next;
}

填充它的每个 next 指针,让这个指针指向其下一个右侧节点。如果找不到下一个右侧节点,则将 next 指针设置为 NULL

初始状态下,所有 next 指针都被设置为 NULL

说明:

  • 你只能使用额外常数空间。
  • 使用递归解题也符合要求,本题中递归程序占用的栈空间不算做额外的空间复杂度。
  • 你可以假设它是一个完美二叉树(即所有叶子节点都在同一层,每个父节点都有两个子节点)。

示例:

给定完美二叉树,

     1
/ \
2 3
/ \ / \
4 5 6 7

调用你的函数后,该完美二叉树变为:

     1 -> NULL
/ \
2 -> 3 -> NULL
/ \ / \
4->5->6->7 -> NULL

解题思路:

这道题实际上是树的层序遍历的应用,可以参考之前的博客Binary Tree Level Order Traversal 二叉树层序遍历,既然是遍历,就有递归和非递归两种方法,最好两种方法都要掌握,都要会写。

面先来看递归的解法,由于是完全二叉树,所以若节点的左子结点存在的话,其右子节点必定存在,所以左子结点的next指针可以直接指向其右子节点,对于其右子节点的处理方法是,判断其父节点的next是否为空,若不为空,则指向其next指针指向的节点的左子结点,若为空则指向NULL。

C++解法一:

 // Recursion, more than constant space
class Solution {
public:
void connect(TreeLinkNode *root) {
if (!root) return;
if (root->left) root->left->next = root->right;
if (root->right) root->right->next = root->next? root->next->left : NULL;
connect(root->left);
connect(root->right);
}
};

对于非递归的解法要稍微复杂一点,但也不算特别复杂,需要用到queue来辅助,由于是层序遍历,每层的节点都按顺序加入queue中,而每当从queue中取出一个元素时,将其next指针指向queue中下一个节点即可。

C++ 解法二:

 // Non-recursion, more than constant space
class Solution {
public:
void connect(TreeLinkNode *root) {
if (!root) return;
queue<TreeLinkNode*> q;
q.push(root);
q.push(NULL);
while (true) {
TreeLinkNode *cur = q.front();
q.pop();
if (cur) {
cur->next = q.front();
if (cur->left) q.push(cur->left);
if (cur->right) q.push(cur->right);
} else {
if (q.size() == || q.front() == NULL) return;
q.push(NULL);
}
}
}
};

上面的方法巧妙的通过给queue中添加空指针NULL来达到分层的目的,使每层的最后一个节点的next可以指向NULL,那么我们可以换一种方法来实现分层,我们对于每层的开头元素开始遍历之前,先统计一下该层的总个数,用个for循环,这样for循环结束的时候,我们就知道该层已经被遍历完了。

C++ 解法三:

 class Solution {
public:
void connect(TreeLinkNode *root) {
if (!root) return;
queue<TreeLinkNode*> q;
q.push(root);
while (!q.empty()) {
int size = q.size();
for (int i = ; i < size; ++i) {
TreeLinkNode *t = q.front(); q.pop();
if (i < size - ) {
t->next = q.front();
}
if (t->left) q.push(t->left);
if (t->right) q.push(t->right);
}
}
}
};

上面三种方法虽然厉害,但是都不符合题意,题目中要求用O(1)的空间复杂度,所以我们来看下面这种碉堡了的方法。用两个指针start和cur,其中start标记每一层的起始节点,cur用来遍历该层的节点,设计思路之巧妙,不得不服。

C++ 解法四:

 class Solution {
public:
void connect(TreeLinkNode *root) {
if (!root) return;
TreeLinkNode *start = root, *cur = NULL;
while (start->left) {
cur = start;
while (cur) {
cur->left->next = cur->right;
if (cur->next) cur->right->next = cur->next->left;
cur = cur->next;
}
start = start->left;
}
}
};

LeetCode(116):填充同一层的兄弟节点的更多相关文章

  1. [leetcode] 116. 填充同一层的兄弟节点

    116. 填充同一层的兄弟节点 其实就是个二叉树的层次遍历 class Solution { public void connect(TreeLinkNode root) { if (root == ...

  2. [leetcode] 117. 填充同一层的兄弟节点 II

    117. 填充同一层的兄弟节点 II 与116. 填充同一层的兄弟节点完全一样,二叉树的层次遍历..这是这次不是完美二叉树了 class Solution { public void connect( ...

  3. 【LeetCode】116#填充同一层的兄弟节点

    题目描述 给定一个二叉树 struct TreeLinkNode { TreeLinkNode *left; TreeLinkNode *right; TreeLinkNode *next; } 填充 ...

  4. LeetCode 116/117. 填充同一层的兄弟节点(Populating Next Right Pointers in Each Node)

    题目描述 给定一个二叉树 struct TreeLinkNode { TreeLinkNode *left; TreeLinkNode *right; TreeLinkNode *next; } 填充 ...

  5. LeetCode(117):填充同一层的兄弟节点 II

    Medium! 题目描述: 给定一个二叉树 struct TreeLinkNode { TreeLinkNode *left; TreeLinkNode *right; TreeLinkNode *n ...

  6. [Java]LeetCode116. 填充同一层的兄弟节点 | Populating Next Right Pointers in Each Node

    Given a binary tree struct TreeLinkNode { TreeLinkNode *left; TreeLinkNode *right; TreeLinkNode *nex ...

  7. [Java]LeetCode117. 填充同一层的兄弟节点 II | Populating Next Right Pointers in Each Node II

    Given a binary tree struct TreeLinkNode { TreeLinkNode *left; TreeLinkNode *right; TreeLinkNode *nex ...

  8. leetcode-每个节点的右向指针(填充同一层的兄弟节点)

    给定一个二叉树 struct TreeLinkNode { TreeLinkNode *left; TreeLinkNode *right; TreeLinkNode *next; } 填充它的每个 ...

  9. Leetcode116. Populating Next Right Pointers in Each Node填充同一层的兄弟节点

    给定一个二叉树 struct TreeLinkNode { TreeLinkNode *left; TreeLinkNode *right; TreeLinkNode *next; } 填充它的每个 ...

随机推荐

  1. 前端与后端的数据交互(jquery ajax+python flask)

    前端与后端的数据交互,最常用的就是GET.POST,比较常用的用法是:提交表单数据到后端,后端返回json 前端的数据发送与接收 1)提交表单数据 2)提交JSON数据 后端的数据接收与响应 1)接收 ...

  2. Jquery简单应用-1.8.3

    Jquery属于什么? javascript的一个库 一个.js文件 用什么用? 可以提高javascript的编程效率 使用流程 用一个html<script type='text/javas ...

  3. jmeter (六) 登录 token获取

    有时候登录请求中会含有token字段,如下,此时就需要提取token 怎么提取token呢,其实很简单,通过正则表达式就可以了 1.添加http请求:获取登录页面,为“get”方式 2.在此http请 ...

  4. HeapByteBuffer与DirectByteBuffer

    HeapByteBuffer,顾名思义,是写在jvm堆上面的一个buffer,底层的本质是一个数组,用类封装维护了很多的索引(limit/position/capacity等) DirectByteB ...

  5. 前端 - jsonp 跨域ajax

    jsonp 跨域ajax原理: 浏览器同源策略限制 如何解决同源策略限制: 方式一: 利用创建script块,在其中执行src属性为 远程url 异域 用函数(返回值) 的形式返回参数 方式二: jq ...

  6. TensorFlow tf.app&tf.app.flags用法介绍

    TensorFlow tf.app&tf.app.flags用法介绍 TensorFlow tf.app argparse  tf.app.flags 下面介绍 tf.app.flags.FL ...

  7. pythonのpygame初体验

    import pygame import sys from pygame.locals import * #初始化pygame pygame.init() size = width,height=60 ...

  8. Web方面的错误, 异常来自hresult:0x80070057(E_INVALIDARG)

    删除 C:/WINDOWS/Microsoft.NET/Framework/v4.0.30319/Temporary ASP.NET files 这个文件夹. 解决方法: 1.代码保存频繁一点.做一个 ...

  9. requests库入门06-post请求

    示例相应的接口文档:GitHub邮箱接口文档 先登录GitHub,然后右上角用户下拉框中选择settings,然后选Emails.可以看到当前账户设置的邮箱情况 再看添加邮箱接口的文档描述,可以通过一 ...

  10. 设计模式C++学习笔记之九(Template Method模板方法模式)

      模板模式也是相当简单的一种模式,而且是比较常用的.模板模式是定义一个操作中的算法的骨架,而将一些步骤延迟到子类中.TemplateMethod使得子类可以不改变一个算法的结构即可重定义该算法的某些 ...