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

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

Given a binary tree

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.

Follow up:

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

Example 1:

Input: root = [1,2,3,4,5,null,7]
Output: [1,#,2,3,#,4,5,7,#]
Explanation: Given the above binary tree (Figure A), your function should populate each next pointer to point to its next right node, just like in Figure B. The serialized output is in level order as connected by the next pointers, with '#' signifying the end of each level.

Constraints:

  • The number of nodes in the given tree is less than 6000.
  • -100 <= node.val <= 100

这道是之前那道 Populating Next Right Pointers in Each Node 的延续,原本的完全二叉树的条件不再满足,但是整体的思路还是很相似,仍然有递归和非递归的解法。我们先来看递归的解法,这里由于子树有可能残缺,故需要平行扫描父节点同层的节点,找到他们的左右子节点。代码如下:

解法一:

class Solution {
public:
    Node* connect(Node* root) {
        if (!root) return NULL;
        Node *p = root->next;
        while (p) {
            if (p->left) {
                p = p->left;
                break;
            }
            if (p->right) {
                p = p->right;
                break;
            }
            p = p->next;
        }
        if (root->right) root->right->next = p;
        if (root->left) root->left->next = root->right ? root->right : p;
        connect(root->right);
        connect(root->left);
        return root;
    }
};

对于非递归的方法,我惊喜的发现之前的方法直接就能用,完全不需要做任何修改,算法思路可参见之前的博客 Populating Next Right Pointers in Each Node,代码如下:

解法二:

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

虽然以上的两种方法都能通过 OJ,但其实它们都不符合题目的要求,题目说只能使用 constant space,可是 OJ 却没有写专门检测 space 使用情况的 test,那么下面贴上 constant space 的解法,这个解法也是用的层序遍历,只不过没有使用 queue 了,我们建立一个 dummy 结点来指向每层的首结点的前一个结点,然后指针 cur 用来遍历这一层,这里实际上是遍历一层,然后连下一层的 next,首先从根结点开始,如果左子结点存在,那么 cur 的 next 连上左子结点,然后 cur 指向其 next 指针;如果 root 的右子结点存在,那么 cur 的 next 连上右子结点,然后 cur 指向其 next 指针。此时 root 的左右子结点都连上了,此时 root 向右平移一位,指向其 next 指针,如果此时 root 不存在了,说明当前层已经遍历完了,重置 cur 为 dummy 结点,root 此时为 dummy->next,即下一层的首结点,然后 dummy 的 next 指针清空,或者也可以将 cur 的 next 指针清空,因为前面已经将 cur 赋值为 dummy 了。那么现在想一想,为什么要清空?因为用 dummy 的目的就是要指到下一行的首结点的位置即 dummy->next,而一旦将 root 赋值为 dummy->next 了之后,这个 dummy 的使命就已经完成了,必须要断开,如果不断开的话,那么假设现在 root 是叶结点了,那么 while 循环还会执行,不会进入前两个 if,然后 root 右移赋空之后,会进入最后一个 if,之前没有断开 dummy->next 的话,那么 root 又指向之前的叶结点了,死循环诞生了,跪了。所以一定要记得清空哦。

这里再来说下 dummy 结点是怎样指向每层的首结点的前一个结点的,过程是这样的,dummy 是创建出来的一个新的结点,其目的是为了指向 root 结点的下一层的首结点的前一个,具体是这么做到的呢,主要是靠 cur 指针,首先 cur 指向 dummy,然后 cur 再连上 root 下一层的首结点,这样 dummy 也就连上了。然后当 root 层遍历完了之后,root 需要往下移动一层,这样 dummy 结点之后连接的位置就正好赋值给 root,然后 cur 再指向 dummy,dummy 之后断开,这样又回到了初始状态,以此往复就可以都连上了,代码如下:

解法三: 

class Solution {
public:
    Node* connect(Node* root) {
        Node *dummy = new Node(-1), *cur = dummy, *head = root;
        while (root) {
            if (root->left) {
                cur->next = root->left;
                cur = cur->next;
            }
            if (root->right) {
                cur->next = root->right;
                cur = cur->next;
            }
            root = root->next;
            if (!root) {
                cur = dummy;
                root = dummy->next;
                dummy->next = NULL;
            }
        }
        return head;
    }
};

类似题目:

Populating Next Right Pointers in Each Node

参考资料:

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

https://leetcode.com/problems/populating-next-right-pointers-in-each-node-ii/discuss/37813/java-solution-with-constant-space

https://leetcode.com/problems/populating-next-right-pointers-in-each-node-ii/discuss/37828/o1-space-on-complexity-iterative-solution

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

(0)

相关推荐

  • C++实现LeetCode(115.不同的子序列)

    [LeetCode] 115. Distinct Subsequences 不同的子序列 Given a string S and a string T, count the number of distinct subsequences of S which equals T. A subsequence of a string is a new string which is formed from the original string by deleting some (can be n

  • C++实现LeetCode(120.三角形)

    [LeetCode] 120.Triangle 三角形 Given a triangle, find the minimum path sum from top to bottom. Each step you may move to adjacent numbers on the row below. For example, given the following triangle [ [2], [3,4], [6,5,7], [4,1,8,3] ] The minimum path sum

  • C++实现LeetCode(141.单链表中的环)

    [LeetCode] 141. Linked List Cycle 单链表中的环 Given a linked list, determine if it has a cycle in it. To represent a cycle in the given linked list, we use an integer pos which represents the position (0-indexed) in the linked list where tail connects to.

  • C++实现LeetCode(114.将二叉树展开成链表)

    [LeetCode] 114. Flatten Binary Tree to Linked List 将二叉树展开成链表 Given a binary tree, flatten it to a linked list in-place. For example, Given 1 / \ 2   5 / \   \ 3   4   6 The flattened tree should look like:    1 \ 2 \ 3 \ 4 \ 5 \ 6 click to show hints

  • C++实现LeetCode(142.单链表中的环之二)

    [LeetCode] 142. Linked List Cycle II 单链表中的环之二 Given a linked list, return the node where the cycle begins. If there is no cycle, return null. To represent a cycle in the given linked list, we use an integer pos which represents the position (0-indexe

  • C++实现LeetCode(111.二叉树的最小深度)

    [LeetCode] 111. Minimum Depth of Binary Tree 二叉树的最小深度 Given a binary tree, find its minimum depth. The minimum depth is the number of nodes along the shortest path from the root node down to the nearest leaf node. Note: A leaf is a node with no child

  • C++实现LeetCode(110.平衡二叉树)

    [LeetCode] 110.Balanced Binary Tree 平衡二叉树 Given a binary tree, determine if it is height-balanced. For this problem, a height-balanced binary tree is defined as: a binary tree in which the depth of the two subtrees of everynode never differ by more t

  • 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;

  • C++实现LeetCode(117.每个节点的右向指针之二)

    [LeetCode] 117. Populating Next Right Pointers in Each Node II 每个节点的右向指针之二 Given a binary tree 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, t

  • C++实现LeetCode(81.在旋转有序数组中搜索之二)

    [LeetCode] 81. Search in Rotated Sorted Array II 在旋转有序数组中搜索之二 Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand. (i.e., [0,0,1,2,2,5,6] might become [2,5,6,0,0,1,2]). You are given a target value to search.

  • C++实现LeetCode(154.寻找旋转有序数组的最小值之二)

    [LeetCode] 154. Find Minimum in Rotated Sorted Array II 寻找旋转有序数组的最小值之二 Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand. (i.e.,  [0,1,2,4,5,6,7] might become  [4,5,6,7,0,1,2]). Find the minimum element. Th

  • C++实现LeetCode(80.有序数组中去除重复项之二)

    [LeetCode] 80. Remove Duplicates from Sorted Array II 有序数组中去除重复项之二 Given a sorted array nums, remove the duplicates in-place such that duplicates appeared at most twice and return the new length. Do not allocate extra space for another array, you mus

  • 二叉树中叶子节点的统计和树高问题

    1.已知二叉树以二叉链表进行存储,其中结点的数据域为data,编写算法,统计二叉树中叶子结点值等于x的结点数目. typedef struct BTNode { int data; struct BTNode *lchild ; //左孩子指针 struct BTNode *rchild; // 右孩子指针 } BTNode;//二叉链表的结构 int num = 0;//用于统计有多少个结点的值与x的值相等 int CountLeaf (BTNode *P, int& num, int x)

  • 详解Redis数据结构之跳跃表

    1.简介 我们先不谈Redis,来看一下跳表. 1.1.业务场景 场景来自小灰的算法之旅,我们需要做一个拍卖行系统,用来查阅和出售游戏中的道具,类似于魔兽世界中的拍卖行那样,还有以下需求: 拍卖行拍卖的商品需要支持四种排序方式,分别是:按价格.按等级.按剩余时间.按出售者ID排序,排序查询要尽可能地快.还要支持输入道具名称的精确查询和不输入名称的全量查询. 这样的业务场景所需要的数据结构该如何设计呢?拍卖行商品列表是线性的,最容易表达线性结构的是数组和链表.假如用有序数组,虽然查找的时候可以使用

  • C++实现LeetCode(78.子集合)

    [LeetCode] 78. Subsets 子集合 Given a set of distinct integers, S, return all possible subsets. Note: Elements in a subset must be in non-descending order. The solution set must not contain duplicate subsets. For example, If S = [1,2,3], a solution is:

  • C++实现LeetCode(156.二叉树的上下颠倒)

    [LeetCode] 156. Binary Tree Upside Down 二叉树的上下颠倒 Given a binary tree where all the right nodes are either leaf nodes with a sibling (a left node that shares the same parent node) or empty, flip it upside down and turn it into a tree where the origina

随机推荐