LeetCode 力扣 116. 填充每個節點的下一個右側節點指針

題目描述(中等難度)

給定一個滿二叉樹,每個節點多了一個next指針,然後將所有的next指針指向它的右邊的節點。並且要求空間複雜度是O(1)

解法一 BFS

如果沒有要求空間複雜度這道題就簡單多了,我們只需要用一個隊列做BFSBFS參見 102 題。然後按順序將每個節點連起來就可以了。

public Node connect(Node root) {
    if (root == null) {
        return root;
    }
    Queue<Node> queue = new LinkedList<Node>();
    queue.offer(root);
    while (!queue.isEmpty()) {
        int size = queue.size();
        Node pre = null;
        for (int i = 0; i < size; i++) {
            Node cur = queue.poll();
            //從第二個節點開始,將前一個節點的 pre 指向當前節點
            if (i > 0) {
                pre.next = cur;
            }
            pre = cur;
            if (cur.left != null) {
                queue.offer(cur.left);
            }
            if (cur.right != null) {
                queue.offer(cur.right);
            }

        }
    }
    return root;
}

解法二 迭代

當然既然題目要求了空間複雜度,那麼我們來考慮下不用隊列該怎麼處理。只需要解決三個問題就夠了。

  • 每一層怎麼遍歷?

    之前是用隊列將下一層的節點保存了起來。

    這裏的話,其實只需要提前把下一層的next構造完成,到了下一層的時候就可以遍歷了。

  • 什麼時候進入下一層?

    之前是得到當前隊列的元素個數,然後遍歷那麼多次。

    這裏的話,注意到最右邊的節點的nextnull,所以可以判斷當前遍歷的節點是不是null

  • 怎麼得到每層開頭節點?

    之前隊列把當前層的所以節點存了起來,得到開頭節點當然很容易。

    這裏的話,我們額外需要一個變量把它存起來。

三個問題都解決了,就可以寫代碼了。利用三個指針,start 指向每層的開始節點,cur指向當前遍歷的節點,pre指向當前遍歷的節點的前一個節點。

如上圖,我們需要把 pre 的左孩子的 next 指向右孩子,pre 的右孩子的next指向cur的左孩子。

如上圖,當 cur 指向 null 以後,我們只需要把 pre 的左孩子的 next 指向右孩子。

public Node connect(Node root) {
    if (root == null) {
        return root;
    }
    Node pre = root;
    Node cur = null;
    Node start = pre;
    while (pre.left != null) {
        //遍歷到了最右邊的節點,要將 pre 和 cur 更新到下一層,並且用 start 記錄
        if (cur == null) {
            //我們只需要把 pre 的左孩子的 next 指向右孩子。
            pre.left.next = pre.right;
            
            pre = start.left;
            cur = start.right;
            start = pre;
        //將下一層的 next 連起來,同時 pre、next 後移
        } else {
            //把 pre 的左孩子的 next 指向右孩子
            pre.left.next = pre.right;
            //pre 的右孩子的 next 指向 cur 的左孩子。
            pre.right.next = cur.left;
            
            pre = pre.next;
            cur = cur.next;
        }
    }
    return root;
}

分享下 leetcode 的高票回答的代碼,看起來更簡潔一些,C++ 寫的。

void connect(TreeLinkNode *root) {
    if (root == NULL) return;
    TreeLinkNode *pre = root;
    TreeLinkNode *cur = NULL;
    while(pre->left) {
        cur = pre;
        while(cur) {
            cur->left->next = cur->right;
            if(cur->next) cur->right->next = cur->next->left;
            cur = cur->next;
        }
        pre = pre->left;
    }
}

我的代碼裏的變量和他的變量對應關係如下。

我的 start    pre    cur
      |       |      |
他的  pre     cur    cur.next

除了變量名不一樣,算法本質還是一樣的。

題目讓我們初始化 next 指針,初始化過程中我們又利用到了next指針,很巧妙了。

更多詳細通俗題解詳見 leetcode.wang

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