Start at one node. Visit every direct neighbor first โ that's ring one. Then every neighbor-of-a-neighbor โ ring two. A queue keeps the order fair: first discovered, first explored.
โ Back to the Field GuideBitta node'dan boshlang. Avval to'g'ridan-to'g'ri barcha qo'shnilarni ko'ring โ bu birinchi halqa. Keyin qo'shnining qo'shnilarini โ ikkinchi halqa. Queue tartibni adolatli saqlaydi: birinchi topilgan โ birinchi ko'riladi.
โ Qo'llanmaga qaytishWatch the graph below: each ring lights up together before the next ring begins โ the queue keeps discovery and visiting order in lockstep, so nothing farther away ever jumps the line.
Quyidagi grafga qarang: keyingi halqa boshlanishidan oldin har bir halqa birgalikda yonadi โ queue topilish va ko'rish tartibini bir xil saqlaydi, shuning uchun uzoqroqdagi hech narsa navbatni buzolmaydi.
visited set. Add the start node to both โ it's discovered before the loop even begins.node.node in the graph.visited: mark it visited and push it onto the back of the queue.start has now been visited, each one discovered in order of its distance (in edges) from start.visited to'plamini yarating. start node'ni ikkalasiga ham qo'shing โ u loop boshlanmasdan oldinoq "topilgan" hisoblanadi.node deb ataymiz.nodening har bir qo'shnisiga qarang.visitedda bo'lmagan har bir qo'shni uchun: uni visited deb belgilang va queue'ning orqasiga qo'shing.startdan yetib boriladigan har bir node endi ko'rilgan, har biri startdan (qirralar bo'yicha) masofasi tartibida topilgan.Time: O(V + E), where V is the number of nodes (vertices) and E is the number of edges. Every node is enqueued and dequeued at most once, thanks to the visited check โ that's O(V) of queue work. And across the whole traversal, every edge gets examined at most once (twice for an undirected graph, once from each endpoint) while scanning neighbor lists โ that's O(E). Add the two together and you get O(V + E): the algorithm does a bounded, constant amount of work per node and per edge, never revisiting either.
Space: O(V). In the worst case โ a "bushy" graph like a star, where one node connects to almost everything โ the queue and the visited set can each hold nearly every node at once. On a grid of R rows and C columns, this becomes O(R ยท C), since every cell is a node.
Vaqt: O(V + E), bu yerda V โ node'lar (vertex'lar) soni, E โ qirralar soni. visited tekshiruvi tufayli har bir node ko'pi bilan bir marta navbatga qo'shiladi va olinadi โ bu O(V) queue ishi. Butun traversal davomida esa, qo'shnilar ro'yxatini skanerlash paytida har bir qirra ko'pi bilan bir marta ko'riladi (yo'naltirilmagan grafda ikki marta โ har bir uchidan bir marta) โ bu O(E). Ikkalasini qo'shsangiz O(V + E) hosil bo'ladi: algoritm har bir node va har bir qirra uchun cheklangan, doimiy ish bajaradi, ikkalasini ham hech qachon qayta ko'rmaydi.
Xotira: O(V). Eng yomon holatda โ yulduz (star) kabi "shoxlagan" grafda, bitta node deyarli hamma narsaga ulangan bo'lsa โ queue va visited to'plami har biri deyarli barcha node'larni bir vaqtda saqlashi mumkin. R qator va C ustunli grid'da esa bu O(R ยท C) ga aylanadi, chunki har bir katak bitta node hisoblanadi.
visited set entirely, or checking it only when a node is popped instead of when it's pushed. Fix: mark a node visited the instant it's added to the queue โ otherwise the same node can be queued by multiple neighbors before any of them is processed, wasting work and, in a graph with a cycle, looping forever.list, e.g. list.pop(0), to simulate a queue. Fix: use collections.deque and popleft() โ removing from the front of a plain list is O(n) per call, silently turning an O(V + E) algorithm into something much slower.start node won't reach every node in the graph. Fix: if you need every node visited (not just those reachable from one start), loop over all nodes and start a fresh BFS from any node not yet in visited.visited to'plamini umuman unutish, yoki uni node navbatga qo'shilganda emas, navbatdan olinganda tekshirish. Yechim: node navbatga qo'shilgan zahoti uni visited deb belgilang โ aks holda bitta node hali hech biri qayta ishlanmasdan turib bir nechta qo'shni tomonidan navbatga qo'shilib qolishi mumkin, bu ishni behuda sarflaydi va cycle bor grafda cheksiz loop'ga olib keladi.list'ning noto'g'ri uchidan olish, masalan list.pop(0). Yechim: collections.deque va popleft() dan foydalaning โ oddiy list'ning boshidan olib tashlash har chaqiriqda O(n) turadi, bu esa O(V + E) algoritmni sezmasdan ancha sekinroq narsaga aylantiradi.start node'dan yagona BFS grafdagi barcha node'larga yetib bormaydi. Yechim: agar barcha node'lar ko'rilishi kerak bo'lsa (nafaqat bitta start'dan yetib boriladiganlar), barcha node'lar bo'ylab loop qiling va hali visitedda bo'lmagan har bir node'dan yangi BFS boshlang.Restated: given a grid where each cell is 0 (empty), 1 (a fresh orange), or 2 (a rotten orange), every minute any fresh orange that is 4-directionally adjacent to a rotten orange becomes rotten too. Return the minimum number of minutes until no cell has a fresh orange left โ or -1 if that's impossible.
start, scan the whole grid first and enqueue every rotten cell's coordinates before the BFS loop begins โ this is called multi-source BFS, and it works exactly like single-source BFS because a queue with several starting items still expands strictly ring by ring.-1 instead.from collections import deque
def orangesRotting(grid):
rows, cols = len(grid), len(grid[0])
queue = deque()
fresh = 0
# Multi-source BFS: every rotten orange starts in the queue
# together, all counted as minute 0 (ring zero).
for r in range(rows):
for c in range(cols):
if grid[r][c] == 2:
queue.append((r, c))
elif grid[r][c] == 1:
fresh += 1
minutes = 0
directions = [(-1, 0), (1, 0), (0, -1), (0, 1)] # up, down, left, right
# Process one full ring (one minute) at a time.
while queue and fresh > 0:
minutes += 1
for _ in range(len(queue)): # everyone currently in the queue is this minute's ring
r, c = queue.popleft()
for dr, dc in directions:
nr, nc = r + dr, c + dc
if 0 <= nr < rows and 0 <= nc < cols and grid[nr][nc] == 1:
grid[nr][nc] = 2 # this fresh orange rots now
fresh -= 1
queue.append((nr, nc)) # it will rot its own neighbors next minute
return minutes if fresh == 0 else -1 # -1: some fresh orange was never reachable
Qayta bayon: har bir katak 0 (bo'sh), 1 (yangi apelsin) yoki 2 (chirigan apelsin) bo'lgan grid berilgan โ har daqiqada chirigan apelsinga 4 yo'nalishda (yuqori/past/chap/o'ng) qo'shni bo'lgan har qanday yangi apelsin ham chiriydi. Hech bir katakda yangi apelsin qolmaguncha ketadigan minimal daqiqalar sonini qaytaring โ yoki bu imkonsiz bo'lsa -1 qaytaring.
startni navbatga qo'shish o'rniga, avval butun grid'ni skanerlang va BFS loop boshlanmasdan oldin har bir chirigan katakning koordinatasini navbatga qo'shing โ bu multi-source BFS deb ataladi, va u xuddi single-source BFS kabi ishlaydi, chunki bir nechta boshlang'ich elementli queue baribir qat'iy halqa-halqa kengayadi.-1 qaytaring.from collections import deque
def orangesRotting(grid):
rows, cols = len(grid), len(grid[0])
queue = deque()
fresh = 0
# Multi-source BFS: every rotten orange starts in the queue
# together, all counted as minute 0 (ring zero).
for r in range(rows):
for c in range(cols):
if grid[r][c] == 2:
queue.append((r, c))
elif grid[r][c] == 1:
fresh += 1
minutes = 0
directions = [(-1, 0), (1, 0), (0, -1), (0, 1)] # up, down, left, right
# Process one full ring (one minute) at a time.
while queue and fresh > 0:
minutes += 1
for _ in range(len(queue)): # everyone currently in the queue is this minute's ring
r, c = queue.popleft()
for dr, dc in directions:
nr, nc = r + dr, c + dc
if 0 <= nr < rows and 0 <= nc < cols and grid[nr][nc] == 1:
grid[nr][nc] = 2 # this fresh orange rots now
fresh -= 1
queue.append((nr, nc)) # it will rot its own neighbors next minute
return minutes if fresh == 0 else -1 # -1: some fresh orange was never reachable