-
[Python] 프로그래머스 / 2024 KAKAO WINTER INTERNSHIP / 주사위 고르기코딩테스트 2024. 10. 1. 17:47
이거, 수학적으로 풀기 쉽지 않다.
문제를 보다보면 이건 마치 확률 및 통계 기법으로 풀릴 것처럼 보인다. 물론 솔직히 푸는 방법이 없을 것 같지는 않은데, 그거 수학적 풀이 생각하고 있느니 그냥 탐색하는 게 더 좋다.
그리고 해보면 알겠지만 수학적 풀이 구현이 더 어려움,,,왜냐하면 문제 조건에서,
N <= 10 조건을 주면서 어디 마음껏 탐색해보라고 속삭이고 있기 때문이다. 세상에 N <= 10이라니, 이건 O(6^N)이라는 말도 안 되는 복잡도의 코드를 구현하라는 것과 같다.그럼에도 불구하고 시간복잡도 초과된 코드
아래의 코드는 brute-force 탐색 코드 치고 상당히 최적화가 잘 된 코드이다. 그럼에도 불구하고 시간복잡도가 초관된다. 어디 마음껏 탐색해보래서 진짜로 탐색했더니, 복잡도가 초과되는 것이다.
#시간복잡도가 초과된 정답코드 from itertools import combinations, product def solution(dices): n = len(dices) perm = list(combinations(range(0, n), n//2)) m = len(perm) best, best_choice = 0, None for i in range(m//2) : my_choice = perm[i] adversarial_choice = perm[m-1-i] my_available_scores = list(product(*[dices[j] for j in my_choice])) adversarial_available_scores = list(product(*[dices[j] for j in adversarial_choice])) my_possibility = 0 adversarial_possibility = 0 rest = 6 ** n for my_score in my_available_scores : for adversarial_score in adversarial_available_scores : rest -= 1 if (a:=sum(my_score)) > (b:=sum(adversarial_score)) : my_possibility += 1 if a < b : adversarial_possibility += 1 if my_possibility + rest < best and adversarial_possibility + rest < best : break if adversarial_possibility > my_possibility : my_choice, adversarial_choice = adversarial_choice, my_choice my_possibility, adversarial_possibility = adversarial_possibility, my_possibility if my_possibility > best : best = my_possibility best_choice = my_choice return sorted([x + 1 for x in best_choice])
정답 코드
이 Velog 포스트를 참고하였다. 여기서 알게된 것이 바로 bisect 모듈인데, 이것은 어떤 unseen 요소가 리스트 내에 만약 끼워넣어진다면 몇 번째로 sort될지를 O(log N)으로 알 수 있게 해주는 모듈이다. 백문이불여일견.
import bisect # 정렬된 리스트 arr = [1, 3, 4, 7, 8] # 숫자 5를 삽입할 위치 찾기 pos = bisect.bisect_left(arr, 5) print(pos) # 출력: 3 # 리스트에 5 삽입 bisect.insort_left(arr, 5) print(arr) # 출력: [1, 3, 4, 5, 7, 8]
물론 리스트의 초기 정렬은 별도로 진행해야 한다. *파이썬의 sort()는 O(N logN)임
bisect를 이용하면 조금 더 효율적으로 이 문제를 풀 수 있다.
from itertools import combinations, product from bisect import bisect_left, bisect_right def solution(dices): n = len(dices) perm = list(combinations(range(0, n), n//2)) m = len(perm) best, best_choice = 0, None for i in range(m//2) : my_choice = perm[i] adversarial_choice = perm[m-1-i] my_available_scores = [] adversarial_available_scores = [] for product_choice in product(range(6), repeat=n//2) : sum_score = 0 for j, k in zip(my_choice, product_choice) : sum_score += dices[j][k] my_available_scores.append(sum_score) sum_score = 0 for j, k in zip(adversarial_choice, product_choice) : sum_score += dices[j][k] adversarial_available_scores.append(sum_score) adversarial_available_scores.sort() my_possibility = 0 adversarial_possibility = 0 for score in my_available_scores: wins = bisect_left(adversarial_available_scores, score) loses = len(adversarial_available_scores) - bisect_right(adversarial_available_scores, score) my_possibility += wins adversarial_possibility += loses if adversarial_possibility > my_possibility : my_possibility, adversarial_possibility = adversarial_possibility, my_possibility my_choice, adversarial_choice = adversarial_choice, my_choice if my_possibility > best: best = my_possibility best_choice = my_choice return sorted([x + 1 for x in best_choice])
'코딩테스트' 카테고리의 다른 글
[Python] 프로그래머스 / 월간 코드 챌린지 시즌1 / 스타 수열 (0) 2024.10.02 [Python] 프로그래머스 / 2020 KAKAO BLIND RECRUITMENT / 기둥과 보 설치 (3) 2024.10.02 [Python] 프로그래머스 / N으로 표현 (0) 2024.09.30 [Python] 프로그래머스 / 가장 긴 팰린드롬 (0) 2024.09.30 [Python] 프로그래머스 / 2019 카카오 개발자 겨울 인턴십 / 징검다리 건너기 (0) 2024.09.28