알고리즘 03

·2023년 8월 25일
0

파이썬

목록 보기
17/18

DFS

깊이 우선 알고리즘
더 이상 찾을 수 없을 때까지 재귀적으로 탐색하는 알고리즘을 말한다.

하나씩 깊이 탐색하는 알고리즘이라 재귀 함수로 구현할 수도 있고 스택으로 구현할 수도 있지만, 나는 재귀함수로 구현하는 편이다. 상대적으로 코드가 직관적이기 때문이다.

graph = {
    1: [2, 3, 4],
    2: [5],
    3: [5],
    4: [],
    5: [6, 7],
    6: [],
    7: [3],
}

# 재귀함수
def dfs_recursive(node, visited):
    # 방문처리
    visited.append(node)

    # 인접 노드 방문
    for adj in graph[node]:
        if adj not in visited:
            dfs_recursive(adj, visited)

    return visited

# 스택 
def dfs_stack(start):
    visited = []
    # 방문할 순서를 담아두는 용도
    stack = [start]

    # 방문할 노드가 남아있는 한 아래 로직을 반복한다.
    while stack:
        # 제일 최근에 삽입된 노드를 꺼내고 방문처리한다.
        top = stack.pop()
        visited.append(top)
        # 인접 노드를 방문한다.
        for adj in graph[top]:
            if adj not in visited:
                stack.append(adj)

    return visited

섬의 개수

2차 배열을 탐색하면서 섬("1")을 하나 발견했을 시 상, 하, 좌, 우 를 재귀적으로 돌면서 섬의 경계선까지 탐색한 뒤, 섬의 개수를 반환하는 알고리즘이다.
스택

def island_dfs_stack(grid):
	# x,y 의 변화량
    dx = [0, 0, 1, -1]
    dy = [1, -1, 0, 0]
    rows, cols = len(grid), len(grid[0])
    cnt = 0
	
    # 이중 반복문을 통해 그리드 탐색
    for row in range(rows):
        for col in range(cols):
        	# 만약 섬이 아니면(0 이면) continue
            if grid[row][col] != '1':
                continue
			# 섬을 발견할 시 cnt += 1 한 뒤 스택에 발견한 섬 추가
            cnt += 1
            stack = [(row, col)]

            while stack:
            # 스택에 남아있는 구역("1")이 없을 때까지 상하좌우 탐색
                x, y = stack.pop()
                grid[x][y] = '0'
                for i in range(4):
                    nx = x + dx[i]
                    ny = y + dy[i]
                    if nx < 0 or nx >= rows or ny < 0 or ny >= cols or grid[nx][ny] != '1':
                        continue
                    stack.append((nx, ny))
    return cnt


assert island_dfs_stack(grid=[
    ["1", "1", "1", "1", "0"],
    ["1", "1", "0", "1", "0"],
    ["1", "1", "0", "0", "0"],
    ["0", "0", "0", "0", "0"]
]) == 1
assert island_dfs_stack(grid=[
    ["1", "1", "0", "0", "0"],
    ["1", "1", "0", "0", "0"],
    ["0", "0", "1", "0", "0"],
    ["0", "0", "0", "1", "1"]
]) == 3

재귀함수

def island_dfs_recursive(grid):
    dx = [0, 0, 1, -1]
    dy = [1, -1, 0, 0]
    m = len(grid)
    n = len(grid[0])
    cnt = 0

    def dfs_recursive(r, c):
        if r < 0 or r >= m or c < 0 or c >= n or grid[r][c] != '1':
            return

        # 방문처리
        grid[r][c] = '0'
        for i in range(4):
            dfs_recursive(r + dx[i], c + dy[i])
        return

    for r in range(m):
        for c in range(n):
            node = grid[r][c]
            if node != '1':
                continue

            cnt += 1
            dfs_recursive(r, c)

    return cnt


assert island_dfs_recursive(grid=[
    ["1", "1", "1", "1", "0"],
    ["1", "1", "0", "1", "0"],
    ["1", "1", "0", "0", "0"],
    ["0", "0", "0", "0", "0"]
]) == 1
assert island_dfs_recursive(grid=[
    ["1", "1", "0", "0", "0"],
    ["1", "1", "0", "0", "0"],
    ["0", "0", "1", "0", "0"],
    ["0", "0", "0", "1", "1"]
]) == 3
profile
공부 중

0개의 댓글