【leetcode】117. 填充每個節點的下一個右側節點指針 II( Populating Next Right Pointers in Each Node II)


題目描述

【leetcode】117. 填充每個節點的下一個右側節點指針 II( Populating Next Right Pointers in Each Node II)

給定一個二叉樹

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

填充它的每個 next 指針,讓這個指針指向其下一個右側節點。如果找不到下一個右側節點,則將 next 指針設置爲 NULL。

初始狀態下,所有 next 指針都被設置爲 NULL。

進階:

  • 你只能使用常量級額外空間。
  • 使用遞歸解題也符合要求,本題中遞歸程序佔用的棧空間不算做額外的空間複雜度。

示例:

輸入:root = [1,2,3,4,5,null,7]
輸出:[1,#,2,3,#,4,5,7,#]
解釋:給定二叉樹如圖 A 所示,你的函數應該填充它的每個 next 指針,以指向其下一個右側節點,如圖 B 所示。

提示:

  • 樹中的節點數小於 6000
  • -100 <= node.val <= 100

第一次解答

思路
這一題顯然使用層次遍歷求解會更簡單,但是通常我們在進行層次遍歷時,每遍歷一層就需要用隊列去存儲下一層的結點,用作下一輪遍歷,顯然不符合進階要求你只能使用常量級額外空間。那麼我們如何在常數額外空間下進行層次遍歷呢?
本題比較特別,每個結點提供了next成員,從每一次最左邊結點沿着next就可以遍歷完該層。
但next默認爲空,我們怎麼得到設置好了的next呢?可以採用自頂向下的方法。對於根節點,我們很容易將其下一層結點連接好,連接好後,就可以對下一層結點進行遍歷,然後對連接下下層結點…以此類推。
這裏有個細節就是,下一層的開始結點,是下一層最左邊的那個結點。具體見代碼。

test case:
[-1,-7,9,null,null,-1,-7,null,8,-9]
[1,2,3,4,5,null,7]
[1,2,3,4,5,null,6,7,null,null,null,null,8]

代碼:

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

        Node* pRoot = root;
        while(nullptr != pRoot){
        	// 拿到這一層的起始結點
            Node* pNode = pRoot;
            Node* pPre = nullptr;
            // 通過next遍歷這一層
            // 將這一層的孩子的next都連接起來
            while(nullptr != pNode){
               if(nullptr != pNode->left){
                    if(nullptr != pPre)
                        pPre->next = pNode->left;
                    pPre = pNode->left;
                }
                if(nullptr != pNode->right){
                    if(nullptr != pPre)
                        pPre->next = pNode->right;
                    pPre = pNode->right;
                }
                pNode = pNode->next;
                
               }
            // 計算下一層起始結點pRoot
            // 下一個pRoot應該是下一層最靠左的結點
            while(nullptr != pRoot && nullptr == pRoot->left && 
                    nullptr == pRoot->right){
                pRoot = pRoot->next;
            }
            if(nullptr != pRoot)
                pRoot = pRoot->left == nullptr ? pRoot->right : pRoot->left;
        }

        return root;
    }
};

結果:

截圖

第二次解答

思路
看了官方題解,找下一層起始結點的工作,可以放在連接孩子的過程中。

代碼:

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

        Node* pRoot = root;
        while(nullptr != pRoot){
        	// 拿到這一層的起始結點
            Node* pNode = pRoot;
            Node* pPre = nullptr;
            pRoot = nullptr;// 置空,由下面找孩子時得到下一層最靠左的結點
            // 通過next遍歷這一層
            // 將這一層的孩子的next都連接起來
            while(nullptr != pNode){
               if(nullptr != pNode->left){
                    if(nullptr != pPre)
                        pPre->next = pNode->left;
                    else
                        pRoot = pNode->left;
                    pPre = pNode->left;
                }
                if(nullptr != pNode->right){
                    if(nullptr != pPre)
                        pPre->next = pNode->right;
                    else
                        pRoot = pNode->right;
                    pPre = pNode->right;
                }
                pNode = pNode->next;
                
               }
            // 下一個pRoot應該是下一層最靠左的結點
            // while(nullptr != pRoot && nullptr == pRoot->left && 
            //         nullptr == pRoot->right){
            //     pRoot = pRoot->next;
            // }
            // if(nullptr != pRoot)
            //     pRoot = pRoot->left == nullptr ? pRoot->right : pRoot->left;
        }

        return root;
    }
};

結果:

在這裏插入圖片描述

相關/參考鏈接

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章