LeetCode 102. 二叉樹的層序遍歷 Binary Tree Level Order Traversal (廣度優(yōu)先搜索(BFS))

102. 二叉樹的層序遍歷

給你一個二叉樹挥下,請你返回其按 層序遍歷 得到的節(jié)點(diǎn)值揍魂。 (即逐層地,從左到右訪問所有節(jié)點(diǎn))棚瘟。

示例:

二叉樹:[3,9,20,null,null,15,7],

 3
/ \
9  20
  /  \
 15   7

返回其層次遍歷結(jié)果:

[
[3],
[9,20],
[15,7]
]
  1. Binary Tree Level Order Traversal

Given a binary tree, return the level order traversal of its nodes' values. (ie, from left to right, level by level).

For example:
Given binary tree [3,9,20,null,null,15,7],

 3
/ \
9  20
  /  \
 15   7

return its level order traversal as:

[
[3],
[9,20],
[15,7]
]

解法

這道題適合用廣度優(yōu)先搜索(BFS)现斋,以及 BFS 適用于什么樣的場景。

DFS(深度優(yōu)先搜索)和 BFS(廣度優(yōu)先搜索)就像孿生兄弟偎蘸,提到一個總是想起另一個庄蹋。然而在實際使用中,我們用 DFS 的時候遠(yuǎn)遠(yuǎn)多于 BFS迷雪。那么限书,是不是 BFS 就沒有什么用呢?

如果我們使用 DFS/BFS 只是為了遍歷一棵樹章咧、一張圖上的所有結(jié)點(diǎn)的話倦西,那么 DFS 和 BFS 的能力沒什么差別,我們當(dāng)然更傾向于更方便寫慧邮、空間復(fù)雜度更低的 DFS 遍歷调限。不過舟陆,某些使用場景是 DFS 做不到的误澳,只能使用 BFS 遍歷。這就是我們要介紹的兩個場景:「層序遍歷」秦躯、「最短路徑」忆谓。

給定一個二叉樹,返回其按層序遍歷得到的節(jié)點(diǎn)值踱承。 層序遍歷即逐層地倡缠、從左到右訪問所有結(jié)點(diǎn)。

什么是層序遍歷呢茎活?簡單來說昙沦,層序遍歷就是把二叉樹分層,然后每一層從左到右遍歷:

乍一看來载荔,這個遍歷順序和 BFS 是一樣的盾饮,我們可以直接用 BFS 得出層序遍歷結(jié)果。然而懒熙,層序遍歷要求的輸入結(jié)果和 BFS 是不同的丘损。層序遍歷要求我們區(qū)分每一層,也就是返回一個二維數(shù)組工扎。而 BFS 的遍歷結(jié)果是一個一維數(shù)組徘钥,無法區(qū)分每一層。

那么肢娘,怎么給 BFS 遍歷的結(jié)果分層呢呈础?我們首先來觀察一下 BFS 遍歷的過程中舆驶,結(jié)點(diǎn)進(jìn)隊列和出隊列的過程:

代碼

package i.levelOrder

import java.util.*

/**
 * @author: Jack
 * 2020-05-13 22:04
 *

 */

fun main() {
    val root = TreeNode(3)
    root.left = TreeNode(9)

    val right = TreeNode(20)
    right.left = TreeNode(15)
    right.right = TreeNode(7)

    root.right = right

    val ans = levelOrder(root)
    println(ans)

    val ans2 = levelOrderRecursive(root)
    println(ans2)

}


/**
 * Example:
 * var ti = TreeNode(5)
 * var v = ti.`val`
 * Definition for a binary tree node.
 * class TreeNode(var `val`: Int) {
 *     var left: TreeNode? = null
 *     var right: TreeNode? = null
 * }
 */


/**
 * Queue Solution
 */
fun levelOrder(root: TreeNode?): List<List<Int>> {
    val ans = mutableListOf<List<Int>>()

    if (null != root) {
        val queue = LinkedList<TreeNode>()
        queue.offer(root)

        while (queue.isNotEmpty()) {
            
            val levelList = mutableListOf<Int>()
            val size = queue.size

            // 此處的for循環(huán)會把當(dāng)前 level 層的所有元素poll出來,同時把下一層待遍歷的節(jié)點(diǎn)放入隊列
            for (i in 0..size - 1) {
                // removes the head (first element) of this list
                val node = queue.poll()
                levelList.add(node.`val`)

                // 把下一層待遍歷的節(jié)點(diǎn)放入隊列尾部 tail (last element) of this list.
                node.left?.let { left -> queue.offer(left) }
                node.right?.let { right -> queue.offer(right) }
            }

            // 每層的List值,存放到ans中
            ans.add(levelList)

        }

    }

    return ans

}


fun levelOrderRecursive(root: TreeNode?): List<List<Int>> {
    val ans = mutableListOf<MutableList<Int>>()
    visitLevel(ans, 0, root)
    return ans
}

fun visitLevel(ans: MutableList<MutableList<Int>>, level: Int, node: TreeNode?) {
    if (null == node) return
    // level 從0 (root) 開始,此時 ans.size = 0; 每層的值存在 levelList 中. 這地方的代碼非常巧妙.
    if (ans.size == level) {
        val levelList = mutableListOf<Int>()
        ans.add(levelList)
    }

    // 當(dāng)前節(jié)點(diǎn)值存到 levelList 中
    ans[level].add(node.`val`)

    val left = node.left
    val right = node.right

    if (null != left)
        visitLevel(ans, level + 1, left)

    if (null != right)
        visitLevel(ans, level + 1, right)

}


class TreeNode(var `val`: Int) {
    var left: TreeNode? = null
    var right: TreeNode? = null
}

參考資料

來源:力扣(LeetCode)
鏈接:https://leetcode-cn.com/problems/binary-tree-level-order-traversal
著作權(quán)歸領(lǐng)扣網(wǎng)絡(luò)所有。商業(yè)轉(zhuǎn)載請聯(lián)系官方授權(quán)猪落,非商業(yè)轉(zhuǎn)載請注明出處贞远。


Kotlin開發(fā)者社區(qū)

專注分享 Java、 Kotlin笨忌、Spring/Spring Boot蓝仲、MySQL、redis官疲、neo4j袱结、NoSQL、Android途凫、JavaScript垢夹、React、Node维费、函數(shù)式編程果元、編程思想、"高可用犀盟,高性能而晒,高實時"大型分布式系統(tǒng)架構(gòu)設(shè)計主題。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末阅畴,一起剝皮案震驚了整個濱河市倡怎,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌贱枣,老刑警劉巖监署,帶你破解...
    沈念sama閱讀 218,858評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異纽哥,居然都是意外死亡钠乏,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評論 3 395
  • 文/潘曉璐 我一進(jìn)店門春塌,熙熙樓的掌柜王于貴愁眉苦臉地迎上來晓避,“玉大人,你說我怎么就攤上這事摔笤」换” “怎么了?”我有些...
    開封第一講書人閱讀 165,282評論 0 356
  • 文/不壞的土叔 我叫張陵吕世,是天一觀的道長彰触。 經(jīng)常有香客問我,道長命辖,這世上最難降的妖魔是什么况毅? 我笑而不...
    開封第一講書人閱讀 58,842評論 1 295
  • 正文 為了忘掉前任分蓖,我火速辦了婚禮,結(jié)果婚禮上尔许,老公的妹妹穿的比我還像新娘么鹤。我一直安慰自己,他們只是感情好味廊,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,857評論 6 392
  • 文/花漫 我一把揭開白布蒸甜。 她就那樣靜靜地躺著,像睡著了一般余佛。 火紅的嫁衣襯著肌膚如雪柠新。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,679評論 1 305
  • 那天辉巡,我揣著相機(jī)與錄音恨憎,去河邊找鬼。 笑死郊楣,一個胖子當(dāng)著我的面吹牛憔恳,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播净蚤,決...
    沈念sama閱讀 40,406評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼钥组,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了塞栅?” 一聲冷哼從身側(cè)響起者铜,我...
    開封第一講書人閱讀 39,311評論 0 276
  • 序言:老撾萬榮一對情侶失蹤腔丧,失蹤者是張志新(化名)和其女友劉穎放椰,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體愉粤,經(jīng)...
    沈念sama閱讀 45,767評論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡砾医,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了衣厘。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片如蚜。...
    茶點(diǎn)故事閱讀 40,090評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖影暴,靈堂內(nèi)的尸體忽然破棺而出错邦,到底是詐尸還是另有隱情,我是刑警寧澤型宙,帶...
    沈念sama閱讀 35,785評論 5 346
  • 正文 年R本政府宣布撬呢,位于F島的核電站,受9級特大地震影響妆兑,放射性物質(zhì)發(fā)生泄漏魂拦。R本人自食惡果不足惜毛仪,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,420評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望芯勘。 院中可真熱鬧箱靴,春花似錦、人聲如沸荷愕。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽安疗。三九已至狈癞,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間茂契,已是汗流浹背蝶桶。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評論 1 271
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留掉冶,地道東北人真竖。 一個月前我還...
    沈念sama閱讀 48,298評論 3 372
  • 正文 我出身青樓,卻偏偏與公主長得像厌小,于是被迫代替她去往敵國和親恢共。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,033評論 2 355