브루트 포스 탐색(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])