깊이/너비 우선탐색

참고 URL

DFS/BFS

  1. A - B - C - H - D - I - J - M - E - G - K - F - L

  2. A - B- C - D - E - F - G - H - I - J - K - L - M

1번 방식은 한 단계씩 나아가면서 해당 노드와 같은 레벨에 있는 노드들(즉, 형제 노드들)을 먼저 순회하는 방식이다.

이러한 방식을 Breath First Search (너비 우선 탐색, BFS) 라고 한다.

2번 방식은 한 노드의 자식을 타고 끝까지 순회한 다음에, 다시 돌아와서 다른 형제의 자식을 타고 내려가며 순회하는 방식이다.

이러한 방식은 Depth First Search (깊이 우선 탐색, DFS) 라고 한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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', 'K'],
'K': ['J', 'L'],
'L': ['K'],
'M': ['H']
}

BFS (Python)

1
2
3
4
5
6
7
8
9
10
11
12
13
def bfs(graph, start_node):
visit = list()
queue = list()

queue.append(start_node)

while queue:
node = queue.pop(0)
if node not in visit:
visit.append(node)
queue.extend(graph[node])

return visit

DFS (Python)

1
2
3
4
5
6
7
8
9
10
11
12
13
def dfs(graph, start_node):
visit = list()
stack = list()

stack.append(start_node)

while stack:
node = stack.pop()
if node not in visit:
visit.append(node)
stack.extend(graph[node])

return visit

cf) append() vs extend()

1
2
3
4
5
6
x = ["my", "name", "is"]
y = ["kim", "hyun", "soo"]
x.append(y)
# x: ["my", "name", "is", ["kim", "hyun", "soo"]]
x.extend(y)
# x: ["my", "name", "is", "kim", "hyun", "soo"]

타겟 넘버

1
2
3
4
5
6
7
8
9
10
11
def solution(numbers, target):
tree = [0]
for num in numbers:
sub_tree = []
for tree_num in tree:
sub_tree.append(tree_num + num)
sub_tree.append(tree_num - num)
tree = sub_tree

# print("Tree : "+ str(tree))
return tree.count(target)

그래프의 깊이 만큼 더한 값을 리스트에 저장 후 해당 합이 target값과 같다면 count 한다.

1
2
3
4
5
6
7
8
9
numbers = [1, 1, 1, 1, 1]
target = 3

# 1 : Tree : [1, -1]
# 2 : Tree : [2, 0, 0, -2]
# 3 : Tree : [3, 1, 1, -1, 1, -1, -1, -3]
# 4: Tree : [4, 2, 2, 0, 2, 0, 0, -2, 2, 0, 0, -2, 0, -2, -2, -4]
# 5 : Tree : [5, 3, 3, 1, 3, 1, 1, -1, 3, 1, 1, -1, 1, -1, -1, -3, 3, 1, 1, -1, 1, -1, -1, -3, 1, -1, -1, -3, -1, -3, -3, -5]
# return tree.count(target) = 3

네트워크

1차 답안

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
def solution(n, computers):

# 1. 네트워크으 상태를 가지고 있는 배열 생성
# A = [0] * n
# 2. 서로 연결되어 있다면 해당 네트워크의 제외한 나머지 1로 지정
# 0의 개수 + 1 개 => 네트워크의 수

netStat = [0] * n
i = -1
for computer in computers:
i += 1
j = -1
for net in computer:

j += 1
if j != i and net == 1:
netStat[j] = 1

return netStat.count(0) + 1

테스트 케이스 4, 5, 7 실패

1
2
3
n = 5

computers = [[1, 1, 0, 0, 0], [1, 1, 0, 0, 0],[0, 0, 1, 0, 1], [0, 0, 0, 1, 0], [0, 0, 1, 0, 1]]

해당 경우 [A, B] , [C, E], [D] 3개의 네트워크가 생성되지만 return 값은 2로 결과가 다르게 나옵니다.

다른 사람 답안

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
def solution(n, computers):
answer = 0
visit = [0 for _ in range(n)]

def dfs(start):
st = [start]

while st:
com_num = st.pop()
if visit[com_num] == 0:
visit[com_num] = 1
for i in range(len(computers[0])):
if computers[com_num][i] == 1 and visit[i] == 0:
st.append(i)

i = 0
while 0 in visit:
if visit[i] == 0:
dfs(i)
answer += 1
i += 1
return answer

DFS/BFS의 개념에 대해 이해하지 않고 문제만 풀다보니 계속 잘못된 풀이로 이어졌다.

DFS/BFS를 이용하지 않고 해당 문제를 풀어보려 했지만 시간상 너무 오래걸려 해당 문제를 해결하지 못하고 DFS/BFS 개념 정리 후 해당 답안을 참고해 문제를 풀었다.

단어 변환

1차답안

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47

def solution(begin, target, words):
visited = [0] * len(words)

# target이 words에 없다면 바로 0 리턴
if target not in words:
return 0

answer = 0
sm_idx = 0
stack = [begin]

while stack:
st = stack.pop()

if begin == target:
return answer

idx = - 1
break_idx = False
for word in words:
if break_idx == True:
break
idx += 1
sm_idx = 0
tg_idx = 0

for i in range(len(begin)):

if target[i] == st[i]:
tg_idx += 1
# 문자열 중 같은지
if word[i] == st[i]:
sm_idx += 1

if tg_idx == len(word) - 1:
answer += 1
return answer

elif sm_idx == len(word) - 1 and visited[idx] == 0:
visited[idx] = 1
stack.append(word)
answer += 1
break_idx = True
break
return answer

테스트 케이스 1번 통과 불가

2차 답안

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
answer = 0
def dfs(begin,target,words,visited):
global answer
stacks = [begin]

while stacks:
# 스택을 활용한 dfs 구현
stack = stacks.pop()

if stack == target:
return answer

for w in range(0,len(words)):
# 조건 1. 한 개의 알파벳만 다른 경우
if len([i for i in range(0,len(words[w])) if words[w][i]!=stack[i]]) == 1:

if visited[w] != 0:
continue

visited[w] = 1

# stack에 추가
stacks.append(words[w])
print(stack)

# depth +
answer +=1

def solution(begin, target, words):
global answer
if target not in words:
return 0

visited = [0 for i in words]
dfs(begin,target,words,visited)

return answer

여행경로

1차답안

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
def dfs(tickets, begin, visited):

answer = [begin]
stack = [begin]

while(stack):
st = stack.pop()
idx = -1

for ticket in tickets:
idx += 1
if ticket[0] == st and visited[idx] == 0:
visited[idx] = 1
stack.append(ticket[1])
answer.append(ticket[1])
break

return answer

def solution(tickets):
tickets.sort(key= lambda x: x[1])
visited = [0] * len(tickets)
begin = "ICN"
answer = dfs(tickets, begin, visited)

return answer

테스트 1 ,테스트 2 통과불가

case : [[ICN, A], [A, C], [A, D], [D, B], [B, A]]
return : [ICN, A, D, B, A, C]

*** [INC, A, C] 가 되버리면 해당 경로가 끊기기 때문에 다음 경로가 있는지 판단하는 조건을 생각해야한다.***

2차 답안

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
def dfs(tickets, begin, visited, plist):
answer = [begin]
stack = [begin]

while(stack):
st = stack.pop()
idx = -1
for ticket in tickets:
idx += 1
if ticket[0] == st and visited[idx] == 0:
if sum(visited) != len(visited) and ticket[1] in plist:
visited[idx] = 1
stack.append(ticket[1])
answer.append(ticket[1])
break
elif sum(visited) == len(visited) -1:
stack.append(ticket[1])
answer.append(ticket[1])
break

return answer

def solution(tickets):
tickets.sort(key= lambda x: x[1])
visited = [0] * len(tickets)
begin = "ICN"
plist = list(map(lambda x: x[0] , tickets))
answer = dfs(tickets, begin, visited, plist)

return answer

테스트 1 통과 불가

tickets = [[“ICN”, “COO”], [“ICN”, “BOO”], [“COO”, “ICN”], [“BOO”, “DOO”]]

*** 모든 요소를 사용하지 않고 [ICN, ,BOO] 리턴***

3차 답안

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
def solution(tickets):
answer = []
def dfs(start,ticList,path):
path.append(start)
if len(ticList)==1:
path.append(ticList[0][1])
answer.append(path)
return
for t in ticList:
if t[0]==start:
ticList_copy = ticList.copy()
ticList_copy.remove(t)
dfs(t[1],ticList_copy,path.copy())

dfs("ICN",tickets,[])
return min(answer)