Algorithm/solution

< DFS(깊이 우선 탐색) BFS(넓이 우선 탐색) >

dxwny 2024. 5. 15. 03:30

< 개념 >

*정석 이론

dfs는 stack을 사용한다. 재귀적 방법이다..

- 방문한 노드의인접 노드 중 가장 가까운 노드(보통 숫자가 작은 노드)를 stack에 넣고 방문한다.

- 그 방문 노드의 인접 노드 중 가장 가까운 노드(보통 숫자가 작은 노드)를 stack에 넣고 또 방문한다.

- 방문할 인접 노드가 없다면 (=leaf에 다다른 것이다) stack에 넣어놨던 노드를 꺼내어 반복한다. (가장 최근에 들어간 노드가 나오므로, 그 부모 노드가 나와서 거꾸로 거슬러 올라갈 수 있다.)

 

bfs는 queue를 사용한다.

- 방문한 노드의 모든 인접 노드를 queue에 삽입한다.

- queue에서 다음노드를 꺼내어 다시 모든 인접 노드를 탐색한다.

- 방문할 노드가 없을 때까지 반복한다.

 

*

그래프-노드 표현은 인접그래프, 인접행렬로 가능하다.

visit표시를 해줘서 이전에 방문한 곳인지 아닌지 검사한다.

 

< 실전문제 > 

*프로그래머스 dfs/bfs - 타겟넘버

- 사고 과정

일단 왜 dfs, bfs인지 모르겠음...

순차적으로 타겟보다 합 값이 작은 지 큰지 검사.. 는 처음부터 - 붙는 경우를 볼 수 없는데 ..

- 해답 본 후

1. dfs,bfs인 이유

해당 숫자가 +,-되는 모든 경우를 그래프로 표현한다. 이 경우에 대한 이후 숫자의 +,- 경우도 각각 따라붙는다.

그 그래프를 전부 탐색했을 때의 결과와 타겟넘버가 같다면 올바른 경우이다. 아니라면 올바르지 못한 경우. 

2. 그래프 표현하기

이것도 헤맸다 .. 어떻게 그래프로 표현되는 지 생각을 못 했는데, 순차적으로 계산되므로 현재 값에 +,- 경우를 각각 따로 구해서 더한 값을 넣어주면 된다 ..

 

def solution(numbers, target):
    result = [0]
    total = 0
    carculate = []
    for i in range(len(numbers)):
        get = numbers[i] #모든 numbers를 

        for j in range(len(result)): #현재 저장된 모든 계산 결과값에
            if i == len(numbers)-1: #마지막 리프는 다 저장하지 않고 계산해서 값이 타겟과 동일하면 total 카운트만 업해줬다.
                if result[j] + get == target:
                    total += 1
                if result[j] - get == target:
                    total += 1
            else: 
                carculate.append(result[j] + get) # + 하는 경우
                carculate.append(result[j] - get) # - 하는 경우
                if j == len(result)-1: #이전 단계에서의 결과값 저장된 것을 지워주기 위해서
                    result = carculate
                    carculate = []

    return total

 

#엄청난 풀이 ... 재귀(DFS)를 활용

def solution(numbers, target):
    if not numbers and target == 0 :
        return 1
    elif not numbers:
        return 0
    else:
        return solution(numbers[1:], target-numbers[0]) + solution(numbers[1:], target+numbers[0])
		#numbers를 for문 돌리는 대신 1:로 계속 깎아준다 ..
        #경우의 수 개수를 어떻게 뽑아주는 거지?