DFS: Bağlı Bileşenler ve Alan Doldurma
Bağlı bileşenleri saymak, iki boyutlu ızgaradaki ada sayısı problemini çözmek ve görüntü işleme için alan doldurma uygulamak üzere DFS kullanın.
DFS: Bağlı Bileşenler ve Alan Doldurma, CoddyKit'te ücretsiz bir Coding Interview Prep dersidir. Bu, 4 dersinin 3. dersidir. Aşağıdan dersin tamamını ücretsiz okuyabilir, sonra tarayıcıda yerleşik kod editörü ve 7/24 yapay zeka koçu ile uygulamalı olarak pratik yapabilirsin. Bu, Coding Interview Prep öğrenme yolunun bir parçasıdır ve ilerlemeniz web ve CoddyKit uygulaması arasında senkronize olur. Coding Interview Prep kursu toplamda 4 dersten oluşur.
Bağlantılı Bileşenlerin Tanımı
Yönsüz bir grafta bağlantılı bileşen, kümedeki her köşe çifti arasında bir yol bulunan maksimal köşe kümesidir. Tek bir graf birden çok bağlantısız bileşene sahip olabilir. Bağlantılı bileşenleri bulmak, birçok grafik sorusunun temelini oluşturur: gruplama, birleştirme, ada sayma ve hesapları birleştirme işlemlerinin tümü bu temel işleme indirgenebilir.
from collections import defaultdict
# Graph with 3 components: {0,1,2}, {3,4}, {5}
graph = defaultdict(list)
for u, v in [(0,1),(0,2),(1,2),(3,4)]:
graph[u].append(v)
graph[v].append(u)
# Node 5 is isolated (no edges)
for node in [0,1,2,3,4,5]:
if node not in graph:
graph[node] = []
# We need DFS or BFS from each unvisited node
# to discover all components
print('Graph has nodes 0-5 with components: {0,1,2}, {3,4}, {5}')DFS ile Bağlantılı Bileşenleri Sayma
Tüm düğümler üzerinde yineleyin. Ziyaret edilmemiş her düğüm için, ulaşılabilen tüm düğümleri ziyaret edildi olarak işaretlemek üzere bir DFS başlatın. Her DFS başlatma işlemi, yeni bir bileşenin keşfedilmesine karşılık gelir. Bileşen sayısını elde etmek için DFS başlatma işlemlerinin sayısını sayın. Bu O(V + E) algoritması, graf bağlantılı olsun veya olmasın doğru çalışır.
from collections import defaultdict
def count_components(n, edges):
graph = defaultdict(list)
for u, v in edges:
graph[u].append(v)
graph[v].append(u)
visited = set()
count = 0
def dfs(node):
visited.add(node)
for nb in graph[node]:
if nb not in visited:
dfs(nb)
for node in range(n):
if node not in visited:
dfs(node)
count += 1
return count
print(count_components(6, [(0,1),(0,2),(1,2),(3,4)])) # 3
print(count_components(5, [(0,1),(1,2),(3,4)])) # 2Ada Sayısı
Ada Sayısı (LeetCode #200), iki boyutlu bir ızgaradaki bağlantılı bileşenler için temel sorudur. Her '1' hücresi bir adaya aittir; bitişik '1' hücreleri (yukarı/aşağı/sol/sağ) aynı adayı oluşturur. DFS kullanarak farklı adaların sayısını bulun: tüm hücreler üzerinde yineleyin; ziyaret edilmemiş bir '1' bulduğunuzda, bağlantılı tüm '1' hücrelerini (boya doldurma) işaretleyen bir DFS başlatın ve ardından sayacı artırın.
def num_islands(grid):
if not grid:
return 0
rows, cols = len(grid), len(grid[0])
count = 0
def dfs(r, c):
if r < 0 or r >= rows or c < 0 or c >= cols:
return
if grid[r][c] != '1':
return
grid[r][c] = '#' # mark visited in-place
dfs(r+1,c); dfs(r-1,c)
dfs(r,c+1); dfs(r,c-1)
for r in range(rows):
for c in range(cols):
if grid[r][c] == '1':
dfs(r, c)
count += 1
return count
grid = [['1','1','0','0','0'],
['1','1','0','0','0'],
['0','0','1','0','0'],
['0','0','0','1','1']]
print(num_islands(grid)) # 3Boya Doldurma Algoritması
Boya Doldurma (LeetCode #733), belirli bir başlangıç rengindeki tüm bağlantılı hücreleri yeni bir renkle değiştirir; tıpkı görüntü düzenleyicilerindeki boya kovası aracı gibi. DFS kullanın: kaynak pikselden başlayarak, özgün renkle eşleşen tüm komşuları özyinelemeli olarak yeniden renklendirin. Dikkat edilmesi gereken temel özel durum şudur: başlangıç hücresinin rengi zaten yeni renge eşitse sonsuz özyinelemeyi önlemek için hemen dönün.
def flood_fill(image, sr, sc, new_color):
original = image[sr][sc]
if original == new_color:
return image # edge case: same color, nothing to do
rows, cols = len(image), len(image[0])
def dfs(r, c):
if r < 0 or r >= rows or c < 0 or c >= cols:
return
if image[r][c] != original:
return
image[r][c] = new_color
dfs(r+1,c); dfs(r-1,c)
dfs(r,c+1); dfs(r,c-1)
dfs(sr, sc)
return image
image = [[1,1,1],[1,1,0],[1,0,1]]
result = flood_fill(image, 1, 1, 2)
for row in result: print(row)
# [[2,2,2],[2,2,0],[2,0,1]]Adaların Maksimum Alanı
Adaların Maksimum Alanı (LeetCode #695), ada sayma işlemini genişletir: her ada için en büyük olanın boyutunu döndürür. DFS taşma doldurma işlemi sırasında işaretlediğiniz hücreleri sayın. DFS, geçerli adanın boyutunu döndürür ve tüm adalar arasındaki maksimum değeri takip edersiniz. Bu, bağlı bileşenler kalıbının basit bir genişletmesidir.
def max_area_of_island(grid):
if not grid:
return 0
rows, cols = len(grid), len(grid[0])
max_area = 0
def dfs(r, c):
if r < 0 or r >= rows or c < 0 or c >= cols:
return 0
if grid[r][c] != 1:
return 0
grid[r][c] = 0 # mark visited
return (1 + dfs(r+1,c) + dfs(r-1,c) +
dfs(r,c+1) + dfs(r,c-1))
for r in range(rows):
for c in range(cols):
if grid[r][c] == 1:
max_area = max(max_area, dfs(r, c))
return max_area
grid = [[0,0,1,0,0,0,0,1,0,0,0,0,0],
[0,0,0,0,0,0,0,1,1,1,0,0,0],
[0,1,1,0,1,0,0,0,0,0,0,0,0],
[0,1,0,0,1,1,0,0,1,0,1,0,0]]
print(max_area_of_island(grid)) # 6Pasifik ve Atlantik'e Su Akışı
Pasifik ve Atlantik'e Su Akışı (LeetCode #417), hangi hücrelerden hem Pasifik (üst/sol kenarlar) hem de Atlantik (alt/sağ kenarlar) okyanuslarına su akabileceğini sorar. Suyun aşağı doğru akışını benzetmek yerine ters DFS kullanın: su okyanuslardan yukarı doğru akar. İki DFS taraması yapın; biri Pasifik sınırlarından, diğeri Atlantik sınırlarından başlayarak ulaşılabilen hücreleri toplayın. Kesişim, cevaptır.
def pacific_atlantic(heights):
rows, cols = len(heights), len(heights[0])
pac = set(); atl = set()
def dfs(r, c, visited, prev_h):
if (r,c) in visited or r < 0 or r >= rows or c < 0 or c >= cols:
return
if heights[r][c] < prev_h:
return # water can't flow uphill in reverse
visited.add((r,c))
for dr, dc in [(0,1),(0,-1),(1,0),(-1,0)]:
dfs(r+dr, c+dc, visited, heights[r][c])
for r in range(rows):
dfs(r, 0, pac, heights[r][0]) # Pacific left
dfs(r, cols-1, atl, heights[r][cols-1]) # Atlantic right
for c in range(cols):
dfs(0, c, pac, heights[0][c]) # Pacific top
dfs(rows-1, c, atl, heights[rows-1][c]) # Atlantic bottom
return sorted(pac & atl) # intersection
print(pacific_atlantic([[1,2,2,3,5],[3,2,3,4,4],[2,4,5,3,1],[6,7,1,4,5],[5,1,1,2,4]]))Bağlı Bileşenler için Yinelemeli DFS
Büyük ızgaralarda Python'ın özyineleme sınırından kaçınmak için yinelemeli DFS'yi (açık bir yığınla) kullanın. Yinelemeli sürüm, özyinelemeli DFS ile eşdeğerdir; ancak çağrı yığını yerine bir yığın kullanır. Başlangıç düğümünü yığına ekleyin, ardından çıkarın, ziyaret edildi olarak işaretleyin ve ziyaret edilmemiş komşuları yığına ekleyin. Bu yöntem, özyinelemeli DFS'nin yığın taşmasına yol açacağı milyonlarca hücreye kadar olan ızgaraları güvenli biçimde işler.
def count_components_iterative(n, edges):
from collections import defaultdict
graph = defaultdict(list)
for u, v in edges:
graph[u].append(v)
graph[v].append(u)
visited = set()
count = 0
for start in range(n):
if start in visited:
continue
# Iterative DFS
stack = [start]
while stack:
node = stack.pop()
if node in visited:
continue
visited.add(node)
for nb in graph[node]:
if nb not in visited:
stack.append(nb)
count += 1
return count
print(count_components_iterative(6, [(0,1),(0,2),(1,2),(3,4)])) # 3Çevrelenmiş Bölgeler
Çevrelenmiş Bölgeler (LeetCode #130), tamamen 'X' sınırlarıyla çevrelenmiş tüm 'O' bölgelerini ele alır. 'O' hücrelerinden herhangi biri ızgaranın kenarına değiyorsa bölge yakalanmaz. İncelik şudur: çevrelenmiş bölgeleri doğrudan bulmak yerine tüm sınırdaki 'O' hücrelerinden DFS başlatın ve ulaşılabilen her şeyi güvenli olarak işaretleyin. Ardından dönüşüm yapın: geriye kalan tüm 'O' hücreleri çevrelenmiştir ve 'X' olur; güvenli hücreler ise yeniden 'O' yapılır.
def solve(board):
if not board:
return
rows, cols = len(board), len(board[0])
def dfs(r, c):
if r < 0 or r >= rows or c < 0 or c >= cols:
return
if board[r][c] != 'O':
return
board[r][c] = 'S' # safe: connected to border
dfs(r+1,c); dfs(r-1,c)
dfs(r,c+1); dfs(r,c-1)
# Mark border-connected O's as safe
for r in range(rows):
dfs(r, 0); dfs(r, cols-1)
for c in range(cols):
dfs(0, c); dfs(rows-1, c)
# Flip: surrounded O -> X, safe S -> O
for r in range(rows):
for c in range(cols):
if board[r][c] == 'O': board[r][c] = 'X'
elif board[r][c] == 'S': board[r][c] = 'O'
board = [['X','X','X','X'],['X','O','O','X'],
['X','X','O','X'],['X','O','X','X']]
solve(board)
print([board[1][1], board[3][1]]) # X, OAlt Adaları Sayma
Alt Adaları Sayma (LeetCode #1905), grid2 içindeki tamamen grid1'deki bir adanın içinde bulunan adaları bulur. grid2'deki her '1' hücresinden DFS başlatın: ziyaret ettiği her hücre grid1'de de '1' ise ada bir alt adadır. İncelik şudur: adanın TÜM hücrelerini ziyaret edin (keşfedildiklerini işaretlemek için), ancak bunların TÜMÜNÜN grid1'de de '1' olup olmadığını takip edin. grid1'deki ilk '0' değerinde işlemi kısa devreyle sonlandırmayın; aksi hâlde aynı adanın diğer hücrelerini işaretlemeyi kaçırırsınız.
def count_sub_islands(grid1, grid2):
rows, cols = len(grid2), len(grid2[0])
def dfs(r, c):
if r < 0 or r >= rows or c < 0 or c >= cols:
return True
if grid2[r][c] != 1:
return True
grid2[r][c] = 0 # mark visited
is_sub = grid1[r][c] == 1 # this cell must be in grid1
is_sub = dfs(r+1,c) and is_sub # note: AND not short-circuit OR
is_sub = dfs(r-1,c) and is_sub
is_sub = dfs(r,c+1) and is_sub
is_sub = dfs(r,c-1) and is_sub
return is_sub
count = 0
for r in range(rows):
for c in range(cols):
if grid2[r][c] == 1 and dfs(r, c):
count += 1
return count
print(count_sub_islands([[1,1,1],[1,0,1],[1,1,1]],
[[1,1,1],[1,0,1],[1,1,1]])) # 1Bağlı Bileşenler için DFS ve BFS Karşılaştırması
Hem DFS hem de BFS, aynı O(V + E) zaman ve O(V) alan karmaşıklığıyla tüm bağlı bileşenleri doğru biçimde bulur. Bağlı bileşen problemlerinde DFS'nin özyinelemeli olarak uygulanması daha basittir; BFS ise kısa yol bilgisine de ihtiyaç duyduğunuzda tercih edilir. Izgara problemlerinde DFS, geri izleme yapmadan önce tek bir yönde derinlemesine ilerlediği ve yakındaki bellek konumlarına sırayla eriştiği için önbellek açısından daha verimlidir.
# DFS advantages for connected components:
# - Simpler recursive implementation
# - Lower constant factor for small graphs
# - Can restore grid state during backtracking (if needed)
# BFS advantages:
# - Finds shortest path while traversing
# - Better for wide, shallow graphs (avoids deep recursion)
# - Multi-source initialisation is natural
# Same asymptotic complexity: O(V + E) time, O(V) space
# Grid (m rows, n cols): O(mn) time and space
print('DFS and BFS: same O(V+E) complexity for component counting')Kısıtlı Adalar: Şekiller ve Çevreler
Adanın Çevresi (LeetCode #463), bir ızgaradaki tek adanın toplam çevresini sayar. Her kara hücresi ('1') için çevreye 4 ekleyin, ardından bitişik her kara hücresi için 2 çıkarın (ortak kenarlar). O(mn) karmaşıklığındaki bu formül tabanlı yaklaşım DFS gerektirmez; ancak bunun sınır kenarlarını sayan bir DFS'ye eşdeğer olduğunu anlamak, ızgara problemleri ile çizge akıl yürütmesi arasındaki bağlantıyı güçlendirir.
def island_perimeter(grid):
rows, cols = len(grid), len(grid[0])
perimeter = 0
for r in range(rows):
for c in range(cols):
if grid[r][c] == 1:
perimeter += 4 # start with 4 sides
# Subtract shared edges with adjacent land cells
if r > 0 and grid[r-1][c] == 1:
perimeter -= 2 # shared top edge
if c > 0 and grid[r][c-1] == 1:
perimeter -= 2 # shared left edge
return perimeter
grid = [[0,1,0,0],[1,1,1,0],[0,1,0,0],[1,1,0,0]]
print(island_perimeter(grid)) # 16Hızlı Kontrol
Bu dersteki Veri Yapıları & Algoritmalar — Kodlama Mülakatı Hazırlığı kavramlarını anlayıp anlamadığınızı sınayın.
Ders Özeti
Bu derste şunları öğrendiniz: ziyaret takibiyle DFS üzerinden bağlı bileşenler, temel 2B ızgara uygulamaları olarak ada sayma ve taşma doldurma ve sınırlardan ters DFS (çevrelenmiş bölgeler) ile kısıt takibiyle çoklu DFS (alt adalar) gibi ileri kalıplar. Sırada yönlü ve yönsüz çizgelerde döngü tespitini ele alacağız.
Sıkça Sorulan Sorular
“DFS: Bağlı Bileşenler ve Alan Doldurma” dersi ücretsiz mi?
Evet — “DFS: Bağlı Bileşenler ve Alan Doldurma” dersin tüm metni burada web'de ücretsiz olarak okunabilir. Etkileşimli olarak pratik yapmak (yerleşik kod editörü ve 7/24 yapay zeka koçu) ve Coding Interview Prep kursunun geri kalanını açmak için CoddyKit PRO'ya yükselt. Coding Interview Prep kursu toplamda 4 dersten oluşur.
“DFS: Bağlı Bileşenler ve Alan Doldurma” dersinde ne öğreneceğim?
Bağlı bileşenleri saymak, iki boyutlu ızgaradaki ada sayısı problemini çözmek ve görüntü işleme için alan doldurma uygulamak üzere DFS kullanın. Coding Interview Prep ile uygulamalı kodu tarayıcıda doğrudan çalıştırarak pratik yaparsın ve 7/24 yapay zeka koçu dersi çalışırken sorularını yanıtlar.
Coding Interview Prep öğrenmeye başlamak için deneyim gerekli mi?
Önceden deneyim gerekmez. CoddyKit'te Coding Interview Prep, başlangıçtan ileri seviyeye kadar yapılandırıldığı için buradan başlayabilir veya başından başlayıp kendi hızında ilerleme yapabilirsin. Bu, 4 dersinin 3. dersidir.
“DFS: Bağlı Bileşenler ve Alan Doldurma” dersi ne kadar sürer?
Çoğu CoddyKit dersi yaklaşık 5–10 dakika sürer. Her biri kısa ve etkileşimli olduğu için sabit ilerleme yaparsın ve web ile uygulama arasında tam olarak bıraktığın yerden devam edebilirsin.
Bu Coding Interview Prep dersinde kod yazıp çalıştırabilir miyim?
Evet. Her Coding Interview Prep dersi yerleşik bir kod editörü içerir, bu sayede tarayıcıda gerçek kod yazıp çalıştırabilir ve anlık yapay zeka geri bildirimi alırsın — yerel kurulum gerekli değildir.
Bu kursun tüm dersleri
- Graf Gösterimleri ve Dolaşım Kurulumu
- BFS: En Kısa Yol ve Seviye Dolaşımı
- DFS: Bağlı Bileşenler ve Alan Doldurma
- Yönlü ve Yönsüz Graflarda Döngü Algılama