LeetCode 力扣 117. 填充每個節(jié)點的下一個右側(cè)節(jié)點指針 II

題目描述(中等難度)

給定一個二叉樹,然后每個節(jié)點有一個 next 指針,將它指向它右邊的節(jié)點。和 116 題 基本一樣扣孟,區(qū)別在于之前是滿二叉樹。

解法一 BFS

直接把 116 題 題的代碼復(fù)制過來就好荣赶,一句也不用改凤价。

利用一個棧將下一層的節(jié)點保存。通過pre指針把棧里的元素一個一個接起來拔创。

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();
            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;
}

解法二

當然題目要求了空間復(fù)雜度利诺,可以先到 116 題 看一下思路,這里在上邊的基礎(chǔ)上改一下剩燥。

我們用第二種簡潔的代碼慢逾,相對會好改一些。

Node connect(Node root) {
    if (root == null)
        return root;
    Node pre = root;
    Node cur = null;
    while (pre.left != null) {
        cur = pre;
        while (cur != null) {
            cur.left.next = cur.right;
            if (cur.next != null) {
                cur.right.next = cur.next.left;
            }
            cur = cur.next;
        }
        pre = pre.left;
    }

    return root;
}

需要解決的問題還是挺多的灭红。

cur.left.next = cur.right;
cur.right.next = cur.next.left;

之前的關(guān)鍵代碼就是上邊兩句侣滩,但是在這道題中我們無法保證cur.left 或者 cur.right 或者 cur.next.left或者cur.next.right 是否為null逸贾。所以我們需要用一個while循環(huán)來保證當前節(jié)點至少有一個孩子漱竖。

while (cur.left == null && cur.right == null) {
    cur = cur.next; 
}

這樣的話保證了當前節(jié)點至少有一個孩子,然后如果一個孩子為 null综膀,那么就可以保證另一個一定不為 null 了赁项。

整體的話葛躏,就用了上邊介紹的技巧澈段,代碼比較長悠菜,可以結(jié)合的看一下。

Node connect(Node root) {
    if (root == null)
        return root;
    Node pre = root;
    Node cur = null;
    while (true) {
        cur = pre;
        while (cur != null) {
            //找到至少有一個孩子的節(jié)點
            if (cur.left == null && cur.right == null) {
                cur = cur.next;
                continue;
            }
            //找到當前節(jié)點的下一個至少有一個孩子的節(jié)點
            Node next = cur.next;
            while (next != null && next.left == null && next.right == null) {
                next = next.next;
                if (next == null) {
                    break;
                }
            }
            //當前節(jié)點的左右孩子都不為空败富,就將 left.next 指向 right
            if (cur.left != null && cur.right != null) {
                cur.left.next = cur.right;
            }
            //要接上 next 的節(jié)點的孩子悔醋,所以用 temp 處理當前節(jié)點 right 為 null 的情況
            Node temp = cur.right == null ? cur.left : cur.right;

            if (next != null) {
                //next 左孩子不為 null,就接上左孩子兽叮。
                if (next.left != null) {
                    temp.next = next.left;
                //next 左孩子為 null芬骄,就接上右孩子猾愿。
                } else {
                    temp.next = next.right;
                }
            }
            
            cur = cur.next;
        }
        //找到擁有孩子的節(jié)點
        while (pre.left == null && pre.right == null) {
            pre = pre.next;
            //都沒有孩子說明已經(jīng)是最后一層了
            if (pre == null) {
                return root;
            }
        }
        //進入下一層
        pre = pre.left != null ? pre.left : pre.right;
    } 
}

解法三

參考 這里

利用解法一的思想账阻,我們利用 pre 指針蒂秘,然后一個一個取節(jié)點,把它連起來淘太。解法一為什么沒有像解法二那樣考慮當前節(jié)點為 null 呢姻僧?因為我們沒有添加為 null 的節(jié)點,就是下邊的代碼的作用蒲牧。

if (cur.left != null) {
    queue.offer(cur.left);
}
if (cur.right != null) {
    queue.offer(cur.right);
}

所以這里是一樣的撇贺,如果當前節(jié)點為null不處理就可以了。

第二個問題冰抢,怎么得到每次的開頭的節(jié)點呢松嘶?我們用一個dummy指針,當連接第一個節(jié)點的時候挎扰,就將dummy指針指向他翠订。此外,之前用的pre指針遵倦,把它當成tail指針可能會更好理解蕴轨。如下圖所示:

cur 指針利用 next 不停的遍歷當前層。

如果 cur 的孩子不為 null 就將它接到 tail 后邊骇吭,然后更新tail橙弱。

curnull 的時候,再利用 dummy 指針得到新的一層的開始節(jié)點燥狰。

dummy 指針在鏈表中經(jīng)常用到棘脐,他只是為了處理頭結(jié)點的情況,它并不屬于當前鏈表龙致。

代碼就異常的簡單了蛀缝。

Node connect(Node root) {
    Node cur = root;
    while (cur != null) {
        Node dummy = new Node();
        Node tail = dummy;
        //遍歷 cur 的當前層
        while (cur != null) {
            if (cur.left != null) {
                tail.next = cur.left;
                tail = tail.next;
            }
            if (cur.right != null) {
                tail.next = cur.right;
                tail = tail.next;
            }
            cur = cur.next;
        }
        //更新 cur 到下一層
        cur = dummy.next;
    }
    return root;
}

本來為了圖方便,在 116 題 的基礎(chǔ)上把解法二改了出來目代,還搞了蠻久屈梁,因為為 null 的情況太多了,不停的報空指針異常榛了,最后終于理清了思路在讶。但和解法三比起來實在是相形見絀了,解法三太優(yōu)雅了霜大,但其實這才是正常的思路构哺,從解法一的做法產(chǎn)生靈感,利用 tail 指針將它們連起來。

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

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末残拐,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子碟嘴,更是在濱河造成了極大的恐慌溪食,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,607評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件娜扇,死亡現(xiàn)場離奇詭異眠菇,居然都是意外死亡,警方通過查閱死者的電腦和手機袱衷,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,239評論 3 395
  • 文/潘曉璐 我一進店門捎废,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人致燥,你說我怎么就攤上這事登疗。” “怎么了嫌蚤?”我有些...
    開封第一講書人閱讀 164,960評論 0 355
  • 文/不壞的土叔 我叫張陵辐益,是天一觀的道長。 經(jīng)常有香客問我脱吱,道長智政,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,750評論 1 294
  • 正文 為了忘掉前任箱蝠,我火速辦了婚禮续捂,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘宦搬。我一直安慰自己牙瓢,他們只是感情好,可當我...
    茶點故事閱讀 67,764評論 6 392
  • 文/花漫 我一把揭開白布间校。 她就那樣靜靜地躺著矾克,像睡著了一般。 火紅的嫁衣襯著肌膚如雪憔足。 梳的紋絲不亂的頭發(fā)上胁附,一...
    開封第一講書人閱讀 51,604評論 1 305
  • 那天,我揣著相機與錄音滓彰,去河邊找鬼控妻。 笑死,一個胖子當著我的面吹牛找蜜,可吹牛的內(nèi)容都是我干的饼暑。 我是一名探鬼主播稳析,決...
    沈念sama閱讀 40,347評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼洗做,長吁一口氣:“原來是場噩夢啊……” “哼弓叛!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起诚纸,我...
    開封第一講書人閱讀 39,253評論 0 276
  • 序言:老撾萬榮一對情侶失蹤撰筷,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后畦徘,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體毕籽,經(jīng)...
    沈念sama閱讀 45,702評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,893評論 3 336
  • 正文 我和宋清朗相戀三年井辆,在試婚紗的時候發(fā)現(xiàn)自己被綠了关筒。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,015評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡杯缺,死狀恐怖蒸播,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情萍肆,我是刑警寧澤袍榆,帶...
    沈念sama閱讀 35,734評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站塘揣,受9級特大地震影響包雀,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜亲铡,卻給世界環(huán)境...
    茶點故事閱讀 41,352評論 3 330
  • 文/蒙蒙 一才写、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧奖蔓,春花似錦琅摩、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,934評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至檀头,卻和暖如春轰异,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背暑始。 一陣腳步聲響...
    開封第一講書人閱讀 33,052評論 1 270
  • 我被黑心中介騙來泰國打工搭独, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人廊镜。 一個月前我還...
    沈念sama閱讀 48,216評論 3 371
  • 正文 我出身青樓牙肝,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子配椭,可洞房花燭夜當晚...
    茶點故事閱讀 44,969評論 2 355

推薦閱讀更多精彩內(nèi)容