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

更新 發佈閱讀 6 分鐘
vocus|新世代的創作平台

這題的題目在這裡: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

演算法

vocus|新世代的創作平台

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

怎麼說呢?

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

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

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

...

其餘依此類推

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

vocus|新世代的創作平台

因為每次轉乘的成本都相同,都是累加次數一次,所以這裡可以使用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
小松鼠的演算法樂園
99會員
428內容數
由有業界實戰經驗的演算法工程師, 手把手教你建立解題的框架, 一步步寫出高效、清晰易懂的解題答案。 著重在讓讀者啟發思考、理解演算法,熟悉常見的演算法模板。 深入淺出地介紹題目背後所使用的演算法意義,融會貫通演算法與資料結構的應用。 在幾個經典的題目融入一道題目的多種解法,或者同一招解不同的題目,擴展廣度,並加深印象。
2024/09/26
Leetcode 729. My Calendar I 給定一個行事曆的class定義和行程安排的介面interface。 請完成下列function 1.建構子MyCalendar() 初始化MyCalendar物件 2.boolean book(int start, int end) 插入新行程
Thumbnail
2024/09/26
Leetcode 729. My Calendar I 給定一個行事曆的class定義和行程安排的介面interface。 請完成下列function 1.建構子MyCalendar() 初始化MyCalendar物件 2.boolean book(int start, int end) 插入新行程
Thumbnail
2024/09/10
Insert Greatest Common Divisors in Linked List 題目給定一個鏈結串列, 請在兩兩節點之間加入一個新節點,新節點的值為兩者之間的最大公因數。 最後返回新串列的head node作為答案。
Thumbnail
2024/09/10
Insert Greatest Common Divisors in Linked List 題目給定一個鏈結串列, 請在兩兩節點之間加入一個新節點,新節點的值為兩者之間的最大公因數。 最後返回新串列的head node作為答案。
Thumbnail
2024/09/09
2326. Spiral Matrix IV 題目給定一個Linked list和對應的矩陣高度m、寬度n。 請依照順時針的拜訪順序, 從左上角出發,依照次序把Linked List的內容填到矩陣裡。 如果有剩餘不足的空位,就填補-1。 最後將填補好的矩陣返回作為答案。
Thumbnail
2024/09/09
2326. Spiral Matrix IV 題目給定一個Linked list和對應的矩陣高度m、寬度n。 請依照順時針的拜訪順序, 從左上角出發,依照次序把Linked List的內容填到矩陣裡。 如果有剩餘不足的空位,就填補-1。 最後將填補好的矩陣返回作為答案。
Thumbnail
看更多
你可能也想看
Thumbnail
《轉轉生》(Re:INCARNATION)為奈及利亞編舞家庫德斯.奧尼奎庫與 Q 舞團創作的當代舞蹈作品,結合拉各斯街頭節奏、Afrobeat/Afrobeats、以及約魯巴宇宙觀的非線性時間,建構出關於輪迴的「誕生—死亡—重生」儀式結構。本文將從約魯巴哲學概念出發,解析其去殖民的身體政治。
Thumbnail
《轉轉生》(Re:INCARNATION)為奈及利亞編舞家庫德斯.奧尼奎庫與 Q 舞團創作的當代舞蹈作品,結合拉各斯街頭節奏、Afrobeat/Afrobeats、以及約魯巴宇宙觀的非線性時間,建構出關於輪迴的「誕生—死亡—重生」儀式結構。本文將從約魯巴哲學概念出發,解析其去殖民的身體政治。
Thumbnail
題目敘述: 給定一個二維陣列的高與寬,並且給定起點位置座標。 請從起點位置開始順時針拜訪陣列元素,並且把沿路走過的座標記錄下來。 以陣列的形式返回答案。
Thumbnail
題目敘述: 給定一個二維陣列的高與寬,並且給定起點位置座標。 請從起點位置開始順時針拜訪陣列元素,並且把沿路走過的座標記錄下來。 以陣列的形式返回答案。
Thumbnail
這是一場修復文化與重建精神的儀式,觀眾不需要完全看懂《遊林驚夢:巧遇Hagay》,但你能感受心與土地團聚的渴望,也不急著在此處釐清或定義什麼,但你的在場感受,就是一條線索,關於如何找著自己的路徑、自己的聲音。
Thumbnail
這是一場修復文化與重建精神的儀式,觀眾不需要完全看懂《遊林驚夢:巧遇Hagay》,但你能感受心與土地團聚的渴望,也不急著在此處釐清或定義什麼,但你的在場感受,就是一條線索,關於如何找著自己的路徑、自己的聲音。
Thumbnail
本文分析導演巴里・柯斯基(Barrie Kosky)如何運用極簡的舞臺配置,將布萊希特(Bertolt Brecht)的「疏離效果」轉化為視覺奇觀與黑色幽默,探討《三便士歌劇》在當代劇場中的新詮釋,並藉由舞臺、燈光、服裝、音樂等多方面,分析該作如何在保留批判核心的同時,觸及觀眾的觀看位置與人性幽微。
Thumbnail
本文分析導演巴里・柯斯基(Barrie Kosky)如何運用極簡的舞臺配置,將布萊希特(Bertolt Brecht)的「疏離效果」轉化為視覺奇觀與黑色幽默,探討《三便士歌劇》在當代劇場中的新詮釋,並藉由舞臺、燈光、服裝、音樂等多方面,分析該作如何在保留批判核心的同時,觸及觀眾的觀看位置與人性幽微。
Thumbnail
這題算是路徑計數類的DP衍伸題(路徑數、方法數、組合數...等等這種枚舉類的題目,第一時間切入除了想到DFS+回溯法之外,也可以留意DP動態規劃解題的可能性) 題目會給我們一個指定長度為arrLen的陣列,起點從index=0開始出發,每次移動可以往左移一格,往右移一格,或是留在原地不
Thumbnail
這題算是路徑計數類的DP衍伸題(路徑數、方法數、組合數...等等這種枚舉類的題目,第一時間切入除了想到DFS+回溯法之外,也可以留意DP動態規劃解題的可能性) 題目會給我們一個指定長度為arrLen的陣列,起點從index=0開始出發,每次移動可以往左移一格,往右移一格,或是留在原地不
Thumbnail
題目會給我們一張資料表Queue,代表乘客排隊上車的情境。 裡面分別有person_id、 person_name 、weight、turn等欄位,分別代表乘客ID、乘客姓名、乘客重量、乘客排隊的順序。 要求我們判斷,在不超重的條件下,最後一位上車的乘客是誰。
Thumbnail
題目會給我們一張資料表Queue,代表乘客排隊上車的情境。 裡面分別有person_id、 person_name 、weight、turn等欄位,分別代表乘客ID、乘客姓名、乘客重量、乘客排隊的順序。 要求我們判斷,在不超重的條件下,最後一位上車的乘客是誰。
Thumbnail
題目會給定我們兩個點座標,分別是起點和終點。 另外,還有一個參數t,代表時間限制。 從起點出發之後,每一秒鐘,我們必須選擇一個N8 8連通的方向,往鄰居的格子點移動。(題目有特別強調,每一秒必須強制移動到下一個格子點,不能停留在原地) 請問我們能不能在時間限制內,從起點走到終點?
Thumbnail
題目會給定我們兩個點座標,分別是起點和終點。 另外,還有一個參數t,代表時間限制。 從起點出發之後,每一秒鐘,我們必須選擇一個N8 8連通的方向,往鄰居的格子點移動。(題目有特別強調,每一秒必須強制移動到下一個格子點,不能停留在原地) 請問我們能不能在時間限制內,從起點走到終點?
Thumbnail
背景:從冷門配角到市場主線,算力與電力被重新定價   小P從2008進入股市,每一個時期的投資亮點都不同,記得2009蘋果手機剛上市,當時蘋果只要在媒體上提到哪一間供應鏈,隔天股價就有驚人的表現,當時光學鏡頭非常熱門,因為手機第一次搭上鏡頭可以拍照,也造就傳統相機廠的殞落,如今手機已經全面普及,題
Thumbnail
背景:從冷門配角到市場主線,算力與電力被重新定價   小P從2008進入股市,每一個時期的投資亮點都不同,記得2009蘋果手機剛上市,當時蘋果只要在媒體上提到哪一間供應鏈,隔天股價就有驚人的表現,當時光學鏡頭非常熱門,因為手機第一次搭上鏡頭可以拍照,也造就傳統相機廠的殞落,如今手機已經全面普及,題
Thumbnail
題目敘述 題目會給我們一個不規則排列的二維陣列,要求我們列出從起點出發,走次對角線,由左下到右上逐層拜訪的路徑。
Thumbnail
題目敘述 題目會給我們一個不規則排列的二維陣列,要求我們列出從起點出發,走次對角線,由左下到右上逐層拜訪的路徑。
Thumbnail
本篇文章討論了在給定二元矩陣中,如何使用Dijkstra算法找出從左上角到右下角的最安全路徑的安全分數。包括定義曼哈頓距離、最安全路徑的算法以及時間複雜度和空間複雜度分析。最終推薦Dijkstra algorithm和priority queue的使用。文章提供了參考文獻LeetCode的連結。
Thumbnail
本篇文章討論了在給定二元矩陣中,如何使用Dijkstra算法找出從左上角到右下角的最安全路徑的安全分數。包括定義曼哈頓距離、最安全路徑的算法以及時間複雜度和空間複雜度分析。最終推薦Dijkstra algorithm和priority queue的使用。文章提供了參考文獻LeetCode的連結。
Thumbnail
題目會給定我們一個輸入陣列connections,和城市的總數目n。 輸入陣列裡面是以pair的方式儲存,(a, b) 分邊代表這條邊的起點和終點。 請問,我們需要改變多少條邊的方向,才能讓每條路徑都指向編號零號的城市( City #0)? 註: 題目還保證,在改變方向之後,一定可以讓每座城
Thumbnail
題目會給定我們一個輸入陣列connections,和城市的總數目n。 輸入陣列裡面是以pair的方式儲存,(a, b) 分邊代表這條邊的起點和終點。 請問,我們需要改變多少條邊的方向,才能讓每條路徑都指向編號零號的城市( City #0)? 註: 題目還保證,在改變方向之後,一定可以讓每座城
Thumbnail
題目會給我們一個routes 陣列,裡面都是分別代表每一條公車路線所對應的公車站編號。 題目要求我們計算出,從起點站source到終點站target的最精簡公車路線搭乘次數是幾次? 也就是說,就是在最少轉乘的前提下,旅途中需要搭乘幾條公車路線?
Thumbnail
題目會給我們一個routes 陣列,裡面都是分別代表每一條公車路線所對應的公車站編號。 題目要求我們計算出,從起點站source到終點站target的最精簡公車路線搭乘次數是幾次? 也就是說,就是在最少轉乘的前提下,旅途中需要搭乘幾條公車路線?
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News