iT邦幫忙

2021 iThome 鐵人賽

DAY 21
0
Software Development

30天用JavaScript刷題刷起來!系列 第 21

Day 21 :廣度優先搜尋 Breadth-First search(BFS)

  • 分享至 

  • xImage
  •  

說到廣度優先搜尋我一定要現知道Queue

Queue(佇列)是先進來的元素先出去(First In First Out = FIFO)的資料結構,通常用於讓程式具有排隊功能,依序執行工作,

而BFS使用queue來確保先被拜訪到的結點(Node),就先成為新的搜尋起點。
以樹(tree)來說會把同一層(level)的節點拜訪完,再繼續向下一層搜尋,直到拜訪完所有節點(queue被清空為止)。

我們繼續拿DFS的圖為例
我們預期得到的結果是[ A, B, C, D, E, F, G, H, I, J, K]
https://ithelp.ithome.com.tw/upload/images/20211006/201417291oR8Gsalrx.png
我們來看圖說故事,我們先準備Queue來讓我們的節點排隊,然後預備一個陣列來記錄結果。

首先,我們在根(Root),也就是A開始拜訪。
我們讓A加入到我們的Queue,
這時候我們發現 「ㄟ~有人在排隊耶」!
於是我們就把它取出來,取出來卻發現他被三個小朋友給抓住了,分別是BCD。
我們從左邊開始優先,就把BCD加到了Queue。
最後A加到我們擺放結果的地方,結束第一回合。

接著我們來到Queue的頭,取出B,按照上面的方式,確認他有沒有被任何小朋友抓住,同樣動作:
加入Queue然後B再放入結果...

這就是我們即將用程式碼實作的流程,在實作之前,我們先來看一下時間複雜度:O(V+E) ,其中V是樹的節點樹,E則是邊數。為什麼?
我們理所當然要拜訪V個點,那E呢?
想想看我們要把一個點的小朋友都加到Queue中,那如果A的小朋友直接就是BCD我們是不是就要確認BCD是不是有小朋友,並把他們加到Queue,那如果像是I沒有小朋友了(沒有edge) ,我們是不是就不需要再去做loop檢查的動作?
而空間複雜度:O(V),有兩個原因:分別是儲存的結果 和 Queue(考慮最糟情況 有可的A下面剛好長滿B~K)

今天的題目其實就是利用一樣的邏輯來實作,差別只是我們要另外把同一層的整理成一個array。
以下就是程式碼的實作

/**
 * Definition for a binary tree node.
 * function TreeNode(val, left, right) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.left = (left===undefined ? null : left)
 *     this.right = (right===undefined ? null : right)
 * }
 */
/**
 * @param {TreeNode} root
 * @return {number[][]}
 */
 
var levelOrder = function(root) {
if (!root) return [];

  const res = [];
  const q = [];
  q.push(root);

  while(q.length) {
    const lvl = [];
    const size = q.length;

    for (let i = 0; i < size; i++) {
      const node = q.shift();
      lvl.push(node.val);
      if (node.left) q.push(node.left);
      if (node.right) q.push(node.right);
    }
    res.push(lvl);
  }
  return res;
};

明日題目預告:驗證二元搜尋樹Validate Binary Search Tree
講了幾天的樹,當然不可以忽略這一題!


上一篇
Day 20 : 深度追蹤 Depth-first-searh
下一篇
Day 22 :Validate BST
系列文
30天用JavaScript刷題刷起來!30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言