문제
프로그래머스
코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.
programmers.co.kr
문제 정리
용어 정리
- 카운트 다운 = 무작위로 정해진 점수를 다트로 깎아서 0점을 만드는 게임
- 점수 설명
싱글 - 해당 수 만큼 점수 얻음(1,2,3....20까지의 점수)
더블 - 해당 수 두 배 만큼 점수 얻음(2,4,6...40까지의 점수)
트리플 - 해당 수 세 배 만큼 점수 얻음(3,6,9....60까지의 점수)
불, 아우터 불 - 50점 얻음
경기 정리
- 한줄 정리: 빨리 0점 만들기, 같으면 '싱글', '불' 최대한 많이 던지기
- 한 게임에는 두 선수 참가
- 교대로 한 번씩 던지는 방식
- 가장 먼저 0점을 만든 선수가 승리
- 두 선수가 같은 라운드에 0점이면, '싱글', '불'을 더 많이 던진 선수가 승리
- 이것도 같으면 선공이 승리
제한사항
- target은 1부터 10만의 범위
접근방법
- 완탐으로 풀면 시간초과일 것
- DP로 풀어야 하지 않을까
코드
def solution(target):
# target까지 도달하는 데 필요한 최소 다트 수와 "싱글" 또는 "불"을 맞춘 횟수를 기록하는 배열
# 최댓값으로 초기화
dp = [[float('inf'), 0] for _ in range(300000)]
# 가능한 과녁 값들
targetList = [i + 1 for i in range(20)]
# 시작 지점의 다트 수는 0으로 초기화
dp[0][0] = 0
# target까지 탐색
for i in range(target):
def updateDart(addIdx, count):
# 던진 다트 수를 갱신할 필요가 있는 경우
if dp[i + addIdx][0] >= dp[i][0] + 1:
if dp[i + addIdx][0] == dp[i][0] + 1:
# 기존 값과 비교하여 "싱글" 또는 "불"을 맞춘 횟수(합) 갱신
dp[i + addIdx][1] = max(dp[i + addIdx][1], dp[i][1] + count)
else:
# 던진 다트 수와 "싱글" 또는 "불"을 맞춘 횟수(합)을 갱신
dp[i + addIdx] = [dp[i][0] + 1, dp[i][1] + count]
# 모든 과녁 값에 대해 확인
for j in targetList:
# 싱글, 더블, 트리플을 순서대로 적용하여 갱신
for multiplier, hitCount in [[1, 1], [2, 0], [3, 0]]:
updateDart(j * multiplier, hitCount)
# "불"에 대해서도 확인하여 갱신
updateDart(50, 1)
# target까지 도달하는 데 필요한 최소 다트 수와 "싱글" 또는 "불"을 맞춘 횟수 반환
return dp[target]
코드의 시간복잡도: O(n)
첫 번째 반복문은 target까지 반복하고, 두 번째 반복문은 targetList의 크기만큼 반복하며, 세 번째 반복문은 상수 시간에 실행 updateDart 함수도 상수 시간에 실행
따라서 전체 시간 복잡도는 O(target * |targetList|)
공간복잡도: O(300,000)
dp 배열의 크기는 300,000이며, 각 원소는 [float('inf'), 0] 형태의 리스트임 따라서 dp 배열의 공간 복잡도는 O(300,000)
- targetList 배열의 크기는 고정되어 있으며, 상수 크기이므로 공간 복잡도에는 영향을 미치지 않음
- updateDart 함수는 상수 공간을 사용하므로 공간 복잡도에는 영향을 미치지 않음
'프로그래밍 > 알고리즘' 카테고리의 다른 글
프로그래머스 - 홀수 vs 짝수 파이썬 (0) | 2023.05.26 |
---|---|
프로그래머스 - 파괴되지 않은 건물 파이썬 (0) | 2023.05.25 |
프로그래머스 - 억억단을 외우자 파이썬 (1) | 2023.05.15 |
프로그래머스 - 같은 숫자는 싫어 파이썬 (0) | 2023.05.08 |
취업과 이직을 위한 프로그래머스 코딩테스트 문제풀이전략 - 배열 (0) | 2023.05.03 |
댓글