happenundo 2024. 6. 26. 13:56
728x90
 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

백트래킹으로 푸는 문제.


 

 

첫번째 풀이 - 시간 초과

from itertools import permutations

def solution(n, k):
    answer = []
    
    candidate_list = list(permutations(range(1, n+1)))
    
    return candidate_list[k - 1]

 

이 문제에서 n의 범위가 20 이하인 자연수이므로 만약 permutations를 통해 구하면 최대 20!만큼의 후보들을 리스트에 저장해야 한다.

그러므로 위 풀이는 불가능하다. 20!개의 원소를 모두 리스트에 저장시킬 수 없기 때문이다.

그래도 혹시 몰라서 제출해봤는데, 역시 효율성 테스트에서 모두 시간초과가 떴다.

 


두번째 풀이 - 정답

import sys
sys.setrecursionlimit(10**5) # 재귀 범위 설정

# num!를 반환하는 함수
def factorial(num):
    if num == 1 or num == 0:
        return 1
    return num * factorial(num - 1)


# 백트래킹
def backTracking(arr, k, result):    
    if len(arr) == 0: # 모든 arr 리스트를 탐색한 경우 result를 반환       
        return result
    
    n = len(arr)
    temp_factorial = factorial(n - 1)
    
    for i in range(n):
        k -= temp_factorial
        if k <= 0: # 만약 k가 0 이하가 되는 경우
            temp = arr[i] # index에 해당하는 arr값을 arr에서 제거하고 result에 추가
            arr.remove(temp)
            result.append(temp)
            return backTracking(arr, k + temp_factorial, result) # 백트래킹

def solution(n, k):
    answer = backTracking(list(range(1, n+1)), k, [])

    return answer

 

백트래킹으로 문제를 쉽게 해결할 수 있다.

 

만약 n이 4이고 k가 17인 경우를 생각해보자.

 

4명의 사람이 줄을 서는 방법은 크게 4가지로 나눌 수 있다.

 

1 - ....

2 - ....

3 - ....

4 - ....

 

그리고 각 방법은 3!만큼의 경우의 수를 가지고 있다.

 

그러므로 n명의 사람이 줄을 서는 방법은 (n-1)명의 사람이 줄을 서는 경우의 수 * n이다.

그러므로 앞 번호에서 부터  k - (n-1)!을 해주면서  k가 0 이하가 되는 경우 그 때의 번호를 result 리스트에 앞에서부터 추가해주면 된다.

 

그리고 백트래킹을 돌아야하므로 기존 arr에서 해당 번호를 제거하고, result 리스트에 해당 번호를 추가해준다. 그리고 k를 갱신해준다.

백트래킹을 돌면서 arr의 길이가 0이 되는 경우, 즉 모든 번호를 탐색한 경우 result 리스트를 반환하면 된다.

 


참고

 

코드는 금방 작성했는데 

# 백트래킹
def backTracking(arr, k, result):    
    ....
            return backTracking(arr, k + temp_factorial, result) # 백트래킹

 

위 코드에서 이 부분을 

 

# 백트래킹
def backTracking(arr, k, result):    
    ....
            backTracking(arr, k + temp_factorial, result) # 백트래킹

 

return을 빼주는 방식으로 코드를 작성했다가 list index out of range 오류가 떠서 이 부분 오류를 찾느라 시간이 오래 걸렸다.

 

백트래킹 문제를 오랜만에 풀어서 기초적인 실수를 했다.

그래도 실수를 통해서 다시 감을 잡아서 다행이다.

728x90