Try   HackMD

廣度優先搜尋BFS

介紹

節點選項是用 先進先出(FIFO) 方式進行管理,所以可以使用佇列的資料結構

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

廣度優先搜尋(BFS)是一種圖形搜尋演算法,從圖的起點開始搜尋,先遍歷所有距離起點為1的節點,再遍歷所有距離起點為2的節點,以此類推直到所有可達節點都被遍歷。 BFS適用於需要找到最短路徑或最少步驟的問題,例如迷宮遊戲或圖形路徑問題

虛擬碼

以下是使用 JavaScript 撰寫的 BFS 演算法的簡易虛擬碼範本:

// 假設圖形表示為鄰接表 adjacency list 的形式 // graph: 圖形,start: 起點,end: 終點 function BFS(graph, start, end) { // 用來保存已訪問的節點 const visited = new Set(); // 用來保存尚未探索的節點 const queue = []; // 將起點加入佇列 queue.push(start); // 標記起點已訪問 visited.add(start); while (queue.length > 0) { // 取出佇列中的下一個節點 const node = queue.shift(); // 如果找到終點,返回路徑 if (node === end) { return true; // 找到終點 } // 對節點的所有鄰接節點進行訪問 for (const neighbor of graph[node]) { // 如果鄰接節點未被訪問,加入佇列 if (!visited.has(neighbor)) { queue.push(neighbor); // 標記鄰接節點已訪問 visited.add(neighbor); } } } return false; // 無法到達終點 } graph = { 1: [2, 3], 2: [1, 4], 3: [1, 4], 4: [2, 3, 5], 5: [4] }; console.log(BFS(graph, 1, 5));

這個 BFS 實現使用 Set 來保存已訪問的節點,使用佇列來保存尚未探索的節點,並在佇列中使用先進先出的方式來探索圖形。

複雜度

時間複雜度

O(V+E)
其中 V 是節點的數量,E 是邊的數量。在最壞的情況下,BFS 將遍歷圖形中的每個節點和每條邊,因此它的時間複雜度與圖形的大小成正比。

空間複雜度

O(V)

因為BFS 使用了一個佇列來保存尚未探索的節點,其中 V 是節點的數量。在最壞的情況下,BFS 需要將圖形中的每個節點都加入佇列,因此空間複雜度也與圖形的大小成正比。

實戰

637. Average of Levels in Binary Tree

題目說明

給定一棵二元數,以數組的形式返回每一層節點的平均值。實際答案在

105 以內的答案將被接受。

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

解法

使用佇列方式層次遍歷,並累加每一層節點的值,計算出每一層節點的平均值,並儲存於陣列中傳回。

/** * 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 averageOfLevels = function(root) { let queue = [root]; let target = []; while (queue.length > 0) { let qlen = queue.length; let row = 0; for (let i = 0; i < qlen; i++) { let {val, left, right} = queue.shift(); row += val; if (left) queue.push(left); if (right) queue.push(right); } target.push(row/qlen); } return target; };