깊이 우선 알고리즘
더 이상 찾을 수 없을 때까지 재귀적으로 탐색하는 알고리즘을 말한다.
하나씩 깊이 탐색하는 알고리즘이라 재귀 함수로 구현할 수도 있고 스택으로 구현할 수도 있지만, 나는 재귀함수로 구현하는 편이다. 상대적으로 코드가 직관적이기 때문이다.
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