
DFS(Depth-First Search)와 백트래킹(Backtracking)은 모두 탐색 알고리즘에서 사용되는 기법입니다.
이 둘은 겉으로 보기에는 유사하지만, 본질적인 차이가 있습니다. 아래에서 차이와 공통점을 정리해 보겠습니다.
- 목적
DFS
- DFS는 주로 그래프 탐색에서 사용되며, 특정 노드에 도달하거나 모든 경로를 탐색하는 것을 목표로 합니다.
- DFS는 탐색의 깊이를 우선적으로 다루고, 경로를 모두 끝까지 탐색한 후에 다음 경로로 넘어갑니다.
백트래킹
- 백트래킹은 특정 조건을 만족하는 해를 찾는 문제에서 사용되며, 유망하지 않은 경로는 미리 배제하는 방식입니다.
- 불필요한 경로를 탐색하지 않도록 조건을 설정해 효율성을 높입니다.
- 유망성 확인
DFS
- 모든 경로를 탐색하는 것이 목적이므로 경로가 유망한지 여부를 따지지 않고 끝까지 탐색합니다.
백트래킹
- 유망성 조건을 확인하여 불필요한 탐색을 피합니다.
- 탐색 도중에 조건이 맞지 않으면 더 깊이 탐색하지 않고, 그 경로를 중단하고 다른 경로를 탐색합니다.
- 적용 범위:
DFS
- 주로 그래프 탐색이나 트리 탐색 문제에서 사용되며, 경로를 찾거나 그래프의 특정 속성을 탐색할 때 사용됩니다.
백트래킹
- 주로 퍼즐 문제(예: N-Queens, Sudoku), 최적화 문제 등에서 사용되며, 조건에 맞는 해를 찾아내는 데 주로 사용됩니다.
DFS
- 장점 -
1. 단순성: DFS는 간단한 구현이 가능하며, 그래프나 트리 탐색 문제에서 기본적으로 사용됩니다.
2. 메모리 효율성: 깊이 우선 탐색은 하나의 경로만 저장하므로, 메모리 사용량이 비교적 적습니다.
- 단점 -
1. 비효율성: 모든 경로를 끝까지 탐색하므로, 불필요한 경로까지 모두 탐색해야 합니다. 최적해를 찾기 위해서는 모든 경로를 살펴야 하므로 시간 복잡도가 높아질 수 있습니다.
2. 무한 루프 가능성**: 사이클이 있는 그래프에서 처리하지 않으면 무한 루프에 빠질 수 있습니다.
백트래킹
- 장점 -
1. 효율성: 유망하지 않은 경로를 미리 배제하므로, 전체 탐색 시간과 자원을 절약할 수 있습니다.
2. 다양한 문제 해결 가능: 퍼즐, 최적화 문제 등 다양한 문제에서 효과적으로 사용됩니다.
- 단점 -
1. 복잡한 구현: 유망성 조건을 정확히 설정해야 하므로, 문제에 따라 구현이 복잡할 수 있습니다.
2. 시간 복잡도: 최악의 경우 모든 경로를 탐색해야 할 수도 있으며, 이 경우 시간 복잡도가 DFS와 동일하게 비효율적일 수 있습니다.
def permute(nums):
result = []
visited = [False] * len(nums) # 각 숫자의 사용 여부를 추적
def backtrack(path):
if len(path) == len(nums):
result.append(' '.join(map(str, path))) # 경로가 완성되면 문자열로 변환해 결과에 추가
return
for i in range(len(nums)):
if not visited[i]: # 아직 사용되지 않은 숫자만 선택
visited[i] = True # 숫자를 사용 처리
path.append(nums[i]) # 경로에 숫자 추가
backtrack(path) # 다음 숫자 선택
path.pop() # 백트래킹: 선택을 취소
visited[i] = False # 숫자를 다시 사용 가능하게 설정
backtrack([]) # 빈 경로에서 시작
return result # 문자열 형식으로 된 결과 리스트 반환
# 사용 예시
nums = [1, 2, 3]
permutations = permute(nums)
for perm in permutations:
print(perm)
DFS와 백트래킹은 모두 재귀적으로 탐색하는 기법이지만, 백트래킹은 유망성을 확인하여 불필요한 경로를 탐색하지 않으므로 더 효율적인 경우가 많습니다.
백트래킹은 순열, 조합, N-Queens 문제와 같은 최적화 문제나 퍼즐 문제에서 매우 유용하게 사용됩니다.
위의 순열 문제를 통해 백트래킹이 어떻게 활용되는지, 그리고 탐색 과정에서의 효율성에 대해 이해할 수 있습니다.