BFS經典應用 最精簡公車路線搭乘次數 Bus Routes_Leetcode #815

更新於 發佈於 閱讀時間約 6 分鐘
raw-image

這題的題目在這裡:Bus Routes

題目敘述

題目會給我們一個routes 陣列,裡面都是分別代表每一條公車路線所對應的公車站編號。

題目要求我們計算出,從起點站source到終點站target的最精簡公車路線搭乘次數是幾次?

也就是說,就是在最少轉乘的前提下,旅途中需要搭乘幾條公車路線?

如果無法抵達,則返回-1


測試範例

Example 1:

Input: routes = [[1,2,7],[3,6,7]], source = 1, target = 6
Output: 2
Explanation: The best strategy is take the first bus to the bus stop 7, then take the second bus to the bus stop 6.

Example 2:

Input: routes = [[7,12],[4,5,15],[6],[15,19],[9,12,13]], source = 15, target = 12
Output: -1

約束條件

Constraints:

  • 1 <= routes.length <= 500.
  • 1 <= routes[i].length <= 10^5
  • All the values of routes[i] are unique.
  • sum(routes[i].length) <= 10^5
  • 0 <= routes[i][j] < 10^6
  • 0 <= source, target < 10^6

演算法

raw-image

這一題可以用圖論的最短路徑演算法來解題。

怎麼說呢?

可以把同一條路線上的公車站都是為同一個虛擬節點

公車路線#0 整個視為一體,視為虛擬節點0。

公車路線#1 整個視為一體,視為虛擬節點1。

...

其餘依此類推

當兩條公車路線有交會在某個公車站時,則兩個虛擬節點有一條邊相連,成本為1,對應到一次轉乘,也就是多一次乘車次數。

raw-image

因為每次轉乘的成本都相同,都是累加次數一次,所以這裡可以使用BFS廣度優先演算法來找最小公車路線搭乘次數。

以起點為出發點,搭乘次數為0次,每踏上一條新的公車路線,路線搭乘次數就+1。

以搭乘公車路線的總次數為層數,由內而外,從1層往外擴散到2層、第3層...依此類推

BFS迭代中,當公車站牌為終點時,此時的擴散層數就是最小公車路線搭乘次數。

BFS迭代結束後,若仍無法抵達終點,則返回-1,代表無解。


程式碼

class Solution:
 def numBusesToDestination(self, routes: List[List[int]], source: int, target: int) -> int:
  
  if source == target:
   # Quick response to simple case
   # No need to take bus if source is equal to target
   return 0

  # key: bus_stop
  # value: busline to corresponding bus_stop
  bus_info = defaultdict(list)

  for busline, route in enumerate(routes):
   for bus_stop in route:
    bus_info[bus_stop].append(busline)
    
  travel_queue = deque( [(source, 0)] )
  visited = set([source])
  bus_line_considered = set()

  # Find shortest bus transfer count from Source to Target
  while travel_queue:
   
   cur_bus_stop, get_on_bus_count = travel_queue.popleft()

   if cur_bus_stop == target: return get_on_bus_count

   for busline in bus_info[cur_bus_stop]:
    
    if busline in bus_line_considered:
     continue

    for other_bus_stop in routes[busline]:
     if other_bus_stop not in visited:
      travel_queue.append((other_bus_stop, get_on_bus_count + 1))
      visited.add(other_bus_stop)
    
    # This busline has been considered, clear to empty to avoid repetition
    #routes[busline] = []
    bus_line_considered.add(busline)

  return -1

複雜度分析

時間複雜度:

最差情況,發生在每個車站都被每條路線包含。

此時建表bus_info的時間成本最大,需耗費O( bus stop count * bust line count)

空間複雜度:

最差情況,發生在每個車站都被每條路線包含。

此時建表bus_info的空間成本最大,需耗費O( bus stop count * bust line count)


關鍵知識點

可以把同一條路線上的公車站都是為同一個虛擬節點

當兩條公車路線有交會在某個公車站時,則兩個虛擬節點有一條邊相連,成本為1,對應到一次轉乘,也就是多一次乘車次數。

因為每次轉乘的成本都相同,都是累加次數一次,所以這裡可以使用BFS廣度優先演算法來找最小公車路線搭乘次數。


Reference:

[1] Python O(m*n) by BFS [+ Visualization] - Bus Routes - LeetCode

avatar-img
90會員
425內容數
由有業界實戰經驗的演算法工程師, 手把手教你建立解題的框架, 一步步寫出高效、清晰易懂的解題答案。 著重在讓讀者啟發思考、理解演算法,熟悉常見的演算法模板。 深入淺出地介紹題目背後所使用的演算法意義,融會貫通演算法與資料結構的應用。 在幾個經典的題目融入一道題目的多種解法,或者同一招解不同的題目,擴展廣度,並加深印象。
留言0
查看全部
avatar-img
發表第一個留言支持創作者!
題目會給我們一個pair陣列,裡面都是原本陣列相鄰元素形成的pair,順序已經被打散。 要求我們從pair陣列重建出原本的陣列。 答案可能有不只一組,任選一組回傳即可。
題目會給定我們兩個點座標,分別是起點和終點。 另外,還有一個參數t,代表時間限制。 從起點出發之後,每一秒鐘,我們必須選擇一個N8 8連通的方向,往鄰居的格子點移動。(題目有特別強調,每一秒必須強制移動到下一個格子點,不能停留在原地) 請問我們能不能在時間限制內,從起點走到終點?
題目會給一顆二元樹,要求我們計算節點值 和 子樹平均值相等的node有幾個。
題目會給我們一顆二元樹的根結點,要求我們找出每一層最大的節點值。
題目會給我們節點總數目n、左子樹的關係陣列、右子樹的關係陣列,要求我們驗證在給定的條件下,能不能構成一顆合法的二元樹。
題目會給我們兩條已經從小到大排序好的串列,要求我們依照從小到大的順序,合併這兩條串列。
題目會給我們一個pair陣列,裡面都是原本陣列相鄰元素形成的pair,順序已經被打散。 要求我們從pair陣列重建出原本的陣列。 答案可能有不只一組,任選一組回傳即可。
題目會給定我們兩個點座標,分別是起點和終點。 另外,還有一個參數t,代表時間限制。 從起點出發之後,每一秒鐘,我們必須選擇一個N8 8連通的方向,往鄰居的格子點移動。(題目有特別強調,每一秒必須強制移動到下一個格子點,不能停留在原地) 請問我們能不能在時間限制內,從起點走到終點?
題目會給一顆二元樹,要求我們計算節點值 和 子樹平均值相等的node有幾個。
題目會給我們一顆二元樹的根結點,要求我們找出每一層最大的節點值。
題目會給我們節點總數目n、左子樹的關係陣列、右子樹的關係陣列,要求我們驗證在給定的條件下,能不能構成一顆合法的二元樹。
題目會給我們兩條已經從小到大排序好的串列,要求我們依照從小到大的順序,合併這兩條串列。
你可能也想看
Google News 追蹤
Thumbnail
隨著理財資訊的普及,越來越多台灣人不再將資產侷限於台股,而是將視野拓展到國際市場。特別是美國市場,其豐富的理財選擇,讓不少人開始思考將資金配置於海外市場的可能性。 然而,要參與美國市場並不只是盲目跟隨標的這麼簡單,而是需要策略和方式,尤其對新手而言,除了選股以外還會遇到語言、開戶流程、Ap
Thumbnail
嘿,大家新年快樂~ 新年大家都在做什麼呢? 跨年夜的我趕工製作某個外包設計案,在工作告一段落時趕上倒數。 然後和兩個小孩過了一個忙亂的元旦。在深夜時刻,看到朋友傳來的解籤網站,興致勃勃熬夜體驗了一下,覺得非常好玩,或許有人玩過了,但還是想寫上來分享紀錄一下~
Thumbnail
1.選擇提早準備路程 2.選擇公車代替捷運 在台北市移動,幾乎都選擇捷運,再走路到達目的地。
Thumbnail
台北捷運最近推出了一個很瘋狂的集章全制霸活動,集滿5條捷運路線(不含環狀線),總共109個車站,就可以抽大獎,本文將使用 Held Karp 算法來計算從台北車站出發,遍歷 109 個車站,並在最後回到台北車站所需花費的最短時間與路徑。
Thumbnail
前言 不知道大家在搭大眾運輸時,更偏好哪一種選擇呢? 繞路但可以一班車抵達,還是直線前進但中間需要換車呢? 假如今天把「目的地」換成我們設定的「目標」,你會選擇前者還是後者呢?
Thumbnail
上下班總是會走到前一個站牌等車,走路運動一下,原站松山車站公車站人太多了,不容易搶到位置,我喜歡先人一步的感覺。 其實走到前兩站也是經常的事,看APP到公車到站時間如果還可以,提前兩站上車沒有坐到位置的機率幾乎為零。 搶到位置坐主要有兩個原因,台北公車急煞急駛真的很不友善,身體一下子被拉長變扭曲
會搭計程車的乘客形形色色,三教九流各式各樣各種類別的人都有。 但這篇文章要寫的是計程車司機最喜歡的乘客類別 。
Thumbnail
旅行中,城市村落間移動的交通工具樣樣種,該如何選擇? 常見的有飛機、火車、公車或包車等幾個選擇,安排行程時,盡可能地在預算和舒適度中找到平衡。此次歐洲自助旅行,唯一團員──75歲老爸──,以客為尊的交通工具安排紀錄。
Thumbnail
又搭錯公車。 上午從木柵回來,想著時間還早,天氣也好,不如搭公車慢慢悠晃回家。 此處有兩班直達住家附近的公車,但都是環狀線,一班去程近,一班回程近。但距上回搭公車已時日久遠,不記得該搭哪一班才對。 想著要先看清楚路線才上車,但走到街口,就看見公車停下來,連猶豫的時間都沒有,於是就上了車。
01/20/2010  公車司機 自助旅行不可或缺的交通工具是什麼? 當然就是公車了 看了地圖,原本威尼斯人就有公車可以搭到今日的第一站媽祖閣. 在威尼斯週圍“繞了一圈“都沒找到. 去過澳門威尼斯人酒店的人,應該了解我所說的繞了一圈是什麼意思.  基本上和跑了 三千公尺 或是健走 五公
Thumbnail
清晨等公車,遇到一台公車很特別,停靠點不是在站牌前,而是至少十步的距離,所有乘客必須往後走十步以上才上得了車。 第一次碰到時,我猜是不是司機心情不好?上車一看,中年司機看來平和,也沒什麼不佳態度,許是特殊情況吧,我這樣想。 第二次又碰到,特意記了一下車號,也特意看了司機一眼,看看下次還有沒有。
Thumbnail
本文探討了竹科交通問題的改善可能性,包括園區巡迴巴士的路線問題,通勤公車路線的概念,竹科巡迴巴士的紅線、綠線問題,橘線、綠能線的改善方法,以及其他公車路線設立和提升公車硬體層面的建議等。
Thumbnail
隨著理財資訊的普及,越來越多台灣人不再將資產侷限於台股,而是將視野拓展到國際市場。特別是美國市場,其豐富的理財選擇,讓不少人開始思考將資金配置於海外市場的可能性。 然而,要參與美國市場並不只是盲目跟隨標的這麼簡單,而是需要策略和方式,尤其對新手而言,除了選股以外還會遇到語言、開戶流程、Ap
Thumbnail
嘿,大家新年快樂~ 新年大家都在做什麼呢? 跨年夜的我趕工製作某個外包設計案,在工作告一段落時趕上倒數。 然後和兩個小孩過了一個忙亂的元旦。在深夜時刻,看到朋友傳來的解籤網站,興致勃勃熬夜體驗了一下,覺得非常好玩,或許有人玩過了,但還是想寫上來分享紀錄一下~
Thumbnail
1.選擇提早準備路程 2.選擇公車代替捷運 在台北市移動,幾乎都選擇捷運,再走路到達目的地。
Thumbnail
台北捷運最近推出了一個很瘋狂的集章全制霸活動,集滿5條捷運路線(不含環狀線),總共109個車站,就可以抽大獎,本文將使用 Held Karp 算法來計算從台北車站出發,遍歷 109 個車站,並在最後回到台北車站所需花費的最短時間與路徑。
Thumbnail
前言 不知道大家在搭大眾運輸時,更偏好哪一種選擇呢? 繞路但可以一班車抵達,還是直線前進但中間需要換車呢? 假如今天把「目的地」換成我們設定的「目標」,你會選擇前者還是後者呢?
Thumbnail
上下班總是會走到前一個站牌等車,走路運動一下,原站松山車站公車站人太多了,不容易搶到位置,我喜歡先人一步的感覺。 其實走到前兩站也是經常的事,看APP到公車到站時間如果還可以,提前兩站上車沒有坐到位置的機率幾乎為零。 搶到位置坐主要有兩個原因,台北公車急煞急駛真的很不友善,身體一下子被拉長變扭曲
會搭計程車的乘客形形色色,三教九流各式各樣各種類別的人都有。 但這篇文章要寫的是計程車司機最喜歡的乘客類別 。
Thumbnail
旅行中,城市村落間移動的交通工具樣樣種,該如何選擇? 常見的有飛機、火車、公車或包車等幾個選擇,安排行程時,盡可能地在預算和舒適度中找到平衡。此次歐洲自助旅行,唯一團員──75歲老爸──,以客為尊的交通工具安排紀錄。
Thumbnail
又搭錯公車。 上午從木柵回來,想著時間還早,天氣也好,不如搭公車慢慢悠晃回家。 此處有兩班直達住家附近的公車,但都是環狀線,一班去程近,一班回程近。但距上回搭公車已時日久遠,不記得該搭哪一班才對。 想著要先看清楚路線才上車,但走到街口,就看見公車停下來,連猶豫的時間都沒有,於是就上了車。
01/20/2010  公車司機 自助旅行不可或缺的交通工具是什麼? 當然就是公車了 看了地圖,原本威尼斯人就有公車可以搭到今日的第一站媽祖閣. 在威尼斯週圍“繞了一圈“都沒找到. 去過澳門威尼斯人酒店的人,應該了解我所說的繞了一圈是什麼意思.  基本上和跑了 三千公尺 或是健走 五公
Thumbnail
清晨等公車,遇到一台公車很特別,停靠點不是在站牌前,而是至少十步的距離,所有乘客必須往後走十步以上才上得了車。 第一次碰到時,我猜是不是司機心情不好?上車一看,中年司機看來平和,也沒什麼不佳態度,許是特殊情況吧,我這樣想。 第二次又碰到,特意記了一下車號,也特意看了司機一眼,看看下次還有沒有。
Thumbnail
本文探討了竹科交通問題的改善可能性,包括園區巡迴巴士的路線問題,通勤公車路線的概念,竹科巡迴巴士的紅線、綠線問題,橘線、綠能線的改善方法,以及其他公車路線設立和提升公車硬體層面的建議等。