C++实现LeetCode(116.每个节点的右向指针)

 更新时间:2021年07月23日 16:07:36   作者:Grandyang  
这篇文章主要介绍了C++实现LeetCode(116.每个节点的右向指针),本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下

[LeetCode] 116. Populating Next Right Pointers in Each Node 每个节点的右向指针

You are given a perfect binary tree where all leaves are on the same level, and every parent has two children. The binary tree has the following definition:

struct Node {
int val;
Node *left;
Node *right;
Node *next;
}

Populate each next pointer to point to its next right node. If there is no next right node, the next pointer should be set to NULL.

Initially, all next pointers are set to NULL.

Example:

Input: {"$id":"1","left":{"$id":"2","left":"$id":"3","left":null,"next":null,"right":null,"val":4},"next":null,"right":{"$id":"4","left":null,"next":null,"right":null,"val":5},"val":2},"next":null,"right":{"$id":"5","left":{"$id":"6","left":null,"next":null,"right":null,"val":6},"next":null,"right":{"$id":"7","left":null,"next":null,"right":null,"val":7},"val":3},"val":1}

Output: {"$id":"1","left":{"$id":"2","left":{"$id":"3","left":null,"next":{"$id":"4","left":null,"next":{"$id":"5","left":null,"next":{"$id":"6","left":null,"next":null,"right":null,"val":7},"right":null,"val":6},"right":null,"val":5},"right":null,"val":4},"next":{"$id":"7","left":{"$ref":"5"},"next":null,"right":{"$ref":"6"},"val":3},"right":{"$ref":"4"},"val":2},"next":null,"right":{"$ref":"7"},"val":1}

Explanation: Given the above perfect binary tree (Figure A), your function should populate each next pointer to point to its next right node, just like in Figure B.

Note:

  • You may only use constant extra space.
  • Recursive approach is fine, implicit stack space does not count as extra space for this problem.

这道题实际上是树的层序遍历的应用,可以参考之前的博客 Binary Tree Level Order Traversal,既然是遍历,就有递归和非递归两种方法,最好两种方法都要掌握,都要会写。下面先来看递归的解法,由于是完全二叉树,所以若节点的左子结点存在的话,其右子节点必定存在,所以左子结点的 next 指针可以直接指向其右子节点,对于其右子节点的处理方法是,判断其父节点的 next 是否为空,若不为空,则指向其 next 指针指向的节点的左子结点,若为空则指向 NULL,代码如下:

解法一:

class Solution {
public:
    Node* connect(Node* root) {
        if (!root) return NULL;
        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);
        return root;
    }
};

对于非递归的解法要稍微复杂一点,但也不算特别复杂,需要用到 queue 来辅助,由于是层序遍历,每层的节点都按顺序加入 queue 中,而每当从 queue 中取出一个元素时,将其 next 指针指向 queue 中下一个节点即可,对于每层的开头元素开始遍历之前,先统计一下该层的总个数,用个 for 循环,这样当 for 循环结束的时候,该层就已经被遍历完了,参见代码如下:

解法二:

// Non-recursion, more than constant space
class Solution {
public:
    Node* connect(Node* root) {
        if (!root) return NULL;
        queue<Node*> q;
        q.push(root);
        while (!q.empty()) {
            int size = q.size();
            for (int i = 0; i < size; ++i) {
                Node *t = q.front(); q.pop();
                if (i < size - 1) {
                    t->next = q.front();
                }
                if (t->left) q.push(t->left);
                if (t->right) q.push(t->right);
            }
        }
        return root;
    }
};

我们再来看下面这种碉堡了的方法,用两个指针 start 和 cur,其中 start 标记每一层的起始节点,cur 用来遍历该层的节点,设计思路之巧妙,不得不服啊:

解法三:

// Non-recursion, constant space
class Solution {
public:
    Node* connect(Node* root) {
        if (!root) return NULL;
        Node *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;
        }
        return root;
    }
};

Github 同步地址:

https://github.com/grandyang/leetcode/issues/116

类似题目:

Populating Next Right Pointers in Each Node II

Binary Tree Right Side View

参考资料:

https://leetcode.com/problems/populating-next-right-pointers-in-each-node/

https://leetcode.com/problems/populating-next-right-pointers-in-each-node/discuss/37473/My-recursive-solution(Java)

https://leetcode.com/problems/populating-next-right-pointers-in-each-node/discuss/37472/A-simple-accepted-solution

到此这篇关于C++实现LeetCode(116.每个节点的右向指针)的文章就介绍到这了,更多相关C++实现每个节点的右向指针内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • C语言如何读取bmp图像

    C语言如何读取bmp图像

    这篇文章主要介绍了C语言如何读取bmp图像,BMP即bitmap,由文件头信息块、图像描述信息块、颜色表、图像数据区四部分组成,下文更多相关资料需要的小伙伴可以参考一下
    2022-04-04
  • C++详解PIMPL指向实现的指针

    C++详解PIMPL指向实现的指针

    PIMPL 是 C++ 中的一个编程技巧,意思为指向实现的指针。具体操作是把类的实现细节放到一个单独的类中,并用一个指针进行访问
    2022-07-07
  • C++虚函数表深入研究

    C++虚函数表深入研究

    这篇文章主要介绍了C++的虚函数表,内容非常详细,思路清晰,需要的朋友可以参考下,希望能够给你带来帮助
    2021-10-10
  • C++实现LeetCode(17.电话号码的字母组合)

    C++实现LeetCode(17.电话号码的字母组合)

    这篇文章主要介绍了C++实现LeetCode(17.电话号码的字母组合),本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-07-07
  • C++中的覆盖和隐藏详解

    C++中的覆盖和隐藏详解

    这篇文章主要介绍了C++中重载、重写(覆盖)和隐藏的区别,是C++面向对象程序设计非常重要的概念,需要的朋友可以参考下,希望能够给你带来帮助
    2021-08-08
  • C语言光标旋转与倒计时功能实现示例详解

    C语言光标旋转与倒计时功能实现示例详解

    这篇文章主要为大家介绍了C语言实现光标旋转与倒计时功能的示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步早日升职加薪
    2021-11-11
  • C++ ReSharper2021激活码永久有效

    C++ ReSharper2021激活码永久有效

    ReSharperC++是为c/c++开发者打造的一款实用Visual Studio扩展插件,这款插件旨在提升开发者的效率,今天给大家分享这款软件的激活方法,需要C++ ReSharper2021激活码的朋友参考下本文
    2021-06-06
  • C/C++中I/O进阶详解及其作用介绍

    C/C++中I/O进阶详解及其作用介绍

    这篇文章主要介绍了C/C++中I/O进阶详解及其作用,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-09-09
  • C++标准模版库(STL)之vector容器详解

    C++标准模版库(STL)之vector容器详解

    vector的功能和水桶一样,就是用来装东西的,并且vector还提供了迭代器来很方便的访问这些数据,下面就让我们一起看下如何使用C++的vector吧
    2023-03-03
  • C语言时间处理实例分享

    C语言时间处理实例分享

    这篇文章主要介绍了C语言时间处理实例分享的相关资料,需要的朋友可以参考下
    2015-07-07

最新评论