0Pricing
Coding Interview Prep · Ders

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)]))          # 2

Ada 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))  # 3

Boya 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))  # 6

Pasifik 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, O

Alt 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]]))  # 1

Bağ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))  # 16

Hı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

  1. Graf Gösterimleri ve Dolaşım Kurulumu
  2. BFS: En Kısa Yol ve Seviye Dolaşımı
  3. DFS: Bağlı Bileşenler ve Alan Doldurma
  4. Yönlü ve Yönsüz Graflarda Döngü Algılama
← Coding Interview Prep Sayfasına Dön