브루트 포스 탐색(Brute-force search): 가능한 모든 경우를 확인.
-Reference. Brute-force search
순차 검색 알고리즘(sequential search algorithm): 리스트에서 특정한 값을 찾는 알고리즘. 리스트에서 찾고자 하는 값을 맨 앞에서부터 끝까지 찾아 나가는 방법.
-Reference. Linear search
순차 탐색 알고리즘을 파이썬으로 구현하면 다음과 같다.
def linear_search(x: int, where: list) -> int:
for i in range(len(where)):
if x == where[i]:
return i
return -1
print(linear_search(3, [1, 2, 3, 4, 5]))
>>> 2
위의 1.1.1. 순차 탐색 알고리즘을 활용하여 다음과 같이 파이썬으로 문제를 풀이할 수 있다.
import sys
import heapq
dwarfs = []
for _ in range(9):
dwarfs.append(int(sys.stdin.readline()))
flag: bool = False
for i in range(8):
for j in range(i+1, 9):
if sum(dwarfs) - dwarfs[i] - dwarfs[j] == 100:
del dwarfs[j]
del dwarfs[i]
flag = True
break
if flag:
break
heapq.heapify(dwarfs)
for _ in range(7):
print(heapq.heappop(dwarfs))

너비 우선 탐색(Breath-first search, BFS): 리(tree) 혹은 그래프(graph) 자료구조를 순회하거나 탐색하는 알고리즘. 하나의 node에서 시작해서 인접한 모든 node들을 우선 방문하여 탐색하는 방법.
-Reference. Breadth-first search
enqueue 후 방문 체크dequeue 하여 해당 노드의 인접 노드 중에서 방문하지 않은 노드를 모두 큐에 enqueue 후 방문 체크너비 우선 탐색 알고리즘을 파이썬으로 구현하면 다음과 같다.
def BFS(graph: dict(), start_node: str) -> list:
visited = []
queue = []
queue.append(start_node)
while queue:
current_node = queue.pop(0)
if current_node not in visited:
visited.append(current_node)
queue.extend(graph[current_node])
return visited
graph = {
'A': ['B'],
'B': ['A', 'C', 'H'],
'C': ['B', 'D'],
'D': ['C', 'E', 'G'],
'E': ['D', 'F'],
'F': ['E'],
'G': ['D'],
'H': ['B', 'I', 'J', 'M'],
'I': ['H'],
'J': ['H'],
'M': ['H']
}
print(BFS(graph, "A"))
>>> ['A', 'B', 'C', 'H', 'D', 'I', 'J', 'M', 'E', 'G', 'F']
위의 1.2.1. 너비 우선 탐색 알고리즘을 활용하여 다음과 같이 파이썬으로 문제를 풀이할 수 있다.
import sys
def BFS(graph: dict(), start_node: int, visited: list()) -> list():
queue = []
count = 1
queue.append(start_node)
while queue:
current_node = queue.pop(0)
if visited[current_node] == 0:
visited[current_node] = count
count += 1
queue.extend(graph[current_node])
return visited
graph = dict()
N, M, R = list(map(int, sys.stdin.readline().split()))
for i in range(N):
graph[i + 1] = []
for _ in range(M):
u, v = list(map(int, sys.stdin.readline().split()))
graph[u].append(v)
graph[v].append(u)
for i in range(N):
graph[i + 1].sort()
visited = [0]*(N+1)
visited = BFS(graph, R, visited)
for i in range(N):
print(visited[i+1])

하지만, BFS 알고리즘의 큐를 list로 구현할 경우 pop() 함수 호출시 원소를 이동해야하므로 시간 복잡도가 증가한다.
따라서, 다음과 같이 파이썬 collections.deque 라이브러리를 사용하여 구현해야 한다.
import sys
from collections import deque
def BFS(graph: dict(), start_node: int, visited: list()) -> list():
queue = deque()
count = 1
queue.append(start_node)
while queue:
current_node = queue.popleft()
if visited[current_node] == 0:
visited[current_node] = count
count += 1
queue.extend(graph[current_node])
return visited
graph = dict()
N, M, R = list(map(int, sys.stdin.readline().split()))
for i in range(N):
graph[i + 1] = []
for _ in range(M):
u, v = list(map(int, sys.stdin.readline().split()))
graph[u].append(v)
graph[v].append(u)
for i in range(N):
graph[i + 1].sort()
visited = [0]*(N+1)
visited = BFS(graph, R, visited)
for i in range(N):
print(visited[i+1])

깊이 우선 탐색(Depth-first search, DFS): 트리(tree) 혹은 그래프(graph) 자료구조를 순회하거나 탐색하는 알고리즘. 하나의 node에서 시작해서 백트래킹(backtracking) 전까지 가능한 멀리 탐색하는 방법.
-Reference. Depth-first search
push 후 방문 체크push 후 방문 체크pop깊이 우선 탐색 알고리즘을 파이썬으로 구현하면 다음과 같다.
def DFS(graph: dict(), start_node: str) -> list():
visited = []
stack = []
stack.append(start_node)
while stack:
current_node = stack.pop()
if current_node not in visited:
visited.append(current_node)
stack.extend(graph[current_node])
return visited
graph = {
'A': ['B'],
'B': ['A', 'C', 'H'],
'C': ['B', 'D'],
'D': ['C', 'E', 'G'],
'E': ['D', 'F'],
'F': ['E'],
'G': ['D'],
'H': ['B', 'I', 'J', 'M'],
'I': ['H'],
'J': ['H'],
'M': ['H']
}
print(DFS(graph, "A"))
>>> ['A', 'B', 'H', 'M', 'J', 'I', 'C', 'D', 'G', 'E', 'F']
위의 1.3.1. 깊이 우선 탐색 알고리즘을 활용하여 다음과 같이 파이썬으로 문제를 풀이할 수 있다.
import sys
from collections import deque
def DFS(graph: dict(), start_node: int, visited: list()) -> list():
stack = deque()
count = 1
stack.append(start_node)
while stack:
current_node = stack.pop()
if visited[current_node] == 0:
visited[current_node] = count
count += 1
stack.extend(graph[current_node])
return visited
N, M, R = list(map(int, sys.stdin.readline().split()))
graph = dict()
for i in range(N):
graph[i+1] = []
for _ in range(M):
u, v = list(map(int, sys.stdin.readline().split()))
graph[u].append(v)
graph[v].append(u)
for i in range(N):
graph[i+1].sort(reverse=True)
visited = [0]*(N+1)
visited = DFS(graph, R, visited)
for i in range(N):
print(visited[i+1])
