티스토리 뷰
1. 문제 설명
(1) 볼링공 고르기
- A, B 두 사람이 서로 무게가 다른 볼링공을 고르려고 한다.
- 볼링공은 총 N개가 있으며 각 볼링공마다 무게가 적혀있고 공의 번호는 1번부터 순서대로 부여된다.
- 같은 무게의 공이 여러 개 있을 수 있지만, 서로 다른 공으로 간주한다.
- 볼링공의 무게는 1부터 M까지 자연수의 형태로 존재한다.
- N개의 공의 무게가 각각 주어질 때, 두 사람이 볼링공을 고르는 조합의 경우의 수를 구하는 프로그램을 작성하시오.
(2) 입력 조건
- 첫째 줄에 볼링공의 개수 N, 공의 최대 무게 M이 공백으로 구분되어 각각 자연수 형태로 주어집니다.(1 <= N <= 1,000, 1 <= M <= 10)
- 둘째 줄에 각 볼링공의 무게 K가 공백으로 구분되어 순서대로 자연수 형태로 주어집니다.(1 <= K <= M)
(3) 출력 조건
- 첫째 줄에 두 사람이 볼링공을 고르는 경우의 수를 출력합니다.
2. 내가 생각한 풀이
(1) 문제 분석
- i번과 j번 등 볼링공의 번호 자체가 중요한 것이 아닌, 무게가 다른 모든 조합의 경우의 수만을 알고 있으면 된다.
- 따라서, 볼링공의 무게가 서로 다른 조합을 모두 만들어 보고 그 조합의 수를 출력하면 될 것이다.
- 입력받은 볼링공의 무게를 오름차순으로 정렬한다.
- 이중 반복문을 이용하여 무게가 낮은 볼링공부터 뒤에 위치하는 볼링공들을 비교해, 무게가 다른 경우에만 조합을 생성한다.
- 생성한 조합을 리스트에 저장한다.
- 반복문이 끝날 경우 '리스트의 길이 == 만들 수 있는 조합의 수' 이므로 리스트의 길이를 출력한다.
(2) 코드 구현
# 볼링공의 개수와 무게 입력
n, m = map(int, input().split())
# 각 볼링공의 무게 입력
k = list(map(int, input().split()))
### 내가 생각한 풀이 방법 ###
data = [] # 볼링공을 선택한 경우의 수를 저장하는 리스트
# 볼링 공의 무게를 낮은 순 부터 오름차순 정렬
k.sort()
for i in range(n):
for j in range(i+1, n):
if k[i] != k[j] and (i, j) not in data:
data.append((i, j))
print(len(data))
(3) 틀린 이유
- 문제 풀이 해설 방법과 비교하니 내 코드는 비효율적이다.
- 조합의 수 자체는 맞는거 같긴 한데, 나는 이중 반복문으로 구현해서 시간 복잡도가 O(n^2)가 되지만 해설에서 설명하는 방법은 O(n)의 시간 복잡도로 구현되어 있다.
3. 문제 풀이 해설
(1) 문제 분석
- 먼저, 무게마다 볼링공이 몇 개 있는지 계산해야 한다.
- 문제의 조건에서 볼링공의 무게는 1부터 최대 10까지 밖에 존재하지 않으므로 길이가 10인 리스트에 각 무게별로 볼링공이 몇 개 존재하는지 기록할 수 있다.
- 그리고 A가 먼저 볼링공을 선택할 때, B가 이어서 볼링공을 선택하는 경우를 차례로 계산하여 경우의 수를 구할 수 있다.
- 입력된 볼링공의 무게가 차례로 [1, 3, 2, 3, 2]일 때,
- 무게가 1인 볼링공의 수 = 1
- 무게가 2인 볼링공의 수 = 2
- 무게가 3인 볼링공의 수 = 2
- A가 무게가 1인 볼링공을 선택했을 때, 만들 수 있는 경우의 수
- (무게가 1인 볼링공의 수) * (B가 선택하는 무게가 2인 볼링공의 수 + B가 선택하는 무게가 3인 볼링공의 수) = 1 * (2+2) = 4
- A가 무게가 2인 볼링공을 선택했을 때, 만들 수 있는 경우의 수
- (무게가 2인 볼링공의 수) * (B가 선택하는 무게가 3인 볼링공의 수) = 2 * 2 = 4
- B는 여기서 무게가 1인 볼링공을 선택할 수 없다.
- 왜냐하면, 조합을 찾는 것이기 때문에 A가 1, B가 2를 선택한 경우와 A가 2, B가 1을 선택한 경우는 결국 같은 경우이다.
- A가 무게가 3인 볼링공을 선택했을 때, 만들 수 있는 경우의 수
- (무게가 3인 볼링공의 수) * (B는 아무 볼링공도 선택할 수 없다.) = 1 * 0 = 0
- 위의 경우와 마찬가지로 조합에서는 A가 1이나 2를 선택했을 때, B가 3을 선택한 경우와 같은 것으로 취급되기 때문에 B는 결과적으로 아무 볼링공도 선택할 수 없다.
- 무게가 낮은 볼링공 부터 차례로 시작하여 남은 볼링공의 갯수를 이용하면 효과적으로 문제를 해결할 수 있다.
(2) 코드 구현
# 볼링공의 개수와 무게 입력
n, m = map(int, input().split())
# 각 볼링공의 무게 입력
k = list(map(int, input().split()))
### 정답 해설 방법 ###
# 1부터 10까지의 무게를 담을 수 있는 리스트
# [0] * (m + 1)로 하는 것이 더 공간을 조금이나마 아낄 수 있을 듯 하다.
array = [0] * 11
for x in k:
# 각 무게에 해당하는 볼링공의 개수 카운트
array[x] += 1
result = 0
# 1부터 m까지의 각 무게에 대하여 처리
for i in range(1, m + 1):
n -= array[i] # 무게가 i인 볼링공의 개수(A가 선택할 수 있는 개수) 제외
# n에는 현재 A가 선택한 볼링공과 같은 무게인 볼링공의 수를 제외한 남은 다른 무게의 볼링공 갯수가 존재
result += array[i] * n # A가 선택한 무게의 볼링공 갯수와 B가 선택할 수 있는 경의 수를 곱해서 더함
print(result)
- 먼저 리스트를 선언하고 무게가 i인 볼링공의 수를 리스트의 i번 인덱스에 저장한다.
- 따라서, 'array[i] = 무게가 i인 볼링공의 수'가 된다.
- 반복문을 통해 무게가 낮은 볼링공부터 경우의 수를 계산한다.
- 전체 볼링공의 수에서 무게 i의 볼링공의 수를 뺀다.
- (무게 i의 볼링공의 수) * (전체 볼링공의 수 - 무게 i의 볼링공의 수)가 'A가 무게 i의 볼링공을 선택했을 때, 만들어질 수 있는 조합의 수'이다.
- 이 계산 결과를 누적하여 마지막에 출력한다.
4. 후기
코드의 효율성에 대해 처음으로 눈으로 확인할 수 있었던 문제였다. 이전 부터 누누이 말했던 것 처럼 문제를 너무 직관적으로 그리고 그대로 해석하려는 버릇이 있다. 그래서 이렇게 패턴을 찾고 코드로 구현할 수 있는 능력이 아직 부족함을 느낀다. 그래도 처음으로 문제의 해석을 봤을 때는 해석을 봐도 약간 이해가 안되는 부분이 있었는데 이제는 뇌구조가 바뀐건지 하도 많이 쳐다봐서 그런건지 확실히 이해하게 되었다. 이 문제 역시 두 번째 풀 때는 정답이었고, 두 달하고 보름정도 뒤에 세 번째 풀때는 또 오답이었는데, 세 번째 풀때 멍청하게 또 이중 반복문으로 구현하려고 했었다.... 그때는 너무 대충 대충 공부하고 넘어갔었나 싶다.
github : Algorithms/q5_0.py at main · LeeSeok-Jun/Algorithms (github.com)
LeeSeok-Jun/Algorithms
Practice algorithms 2020. Contribute to LeeSeok-Jun/Algorithms development by creating an account on GitHub.
github.com
'이것이 취업을 위한 코딩 테스트다 with 파이썬 > 11장_그리디 알고리즘' 카테고리의 다른 글
문제 06 : 무지의 먹방 라이브(난이도 : 1/3) (0) | 2021.06.29 |
---|---|
문제 04 : 만들 수 없는 금액(난이도 : 1/3) (0) | 2021.05.17 |
문제 03 : 문자열 뒤집기(난이도 : 1/3) (0) | 2021.05.17 |
문제 02 : 곱하기 혹은 더하기(난이도 : 1/3) (0) | 2021.05.17 |
문제 01 : 모험가 길드(난이도 : 1/3) (0) | 2021.05.17 |
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
링크
TAG
- 종만북
- 난이도:하
- 그리디
- 마르코프 연쇄
- 동적 계획법
- 난이도:상
- python
- 탐욕법
- 프로그래밍 대회에서 배우는 알고리즘 문제해결 전략
- 프로그래머스
- 구현
- 난이도:중
- 프로그래밍 대회에서 배우는 알고리즘 문제 해결 전략
- 프로그래밍 대회에서 배우는 알고리즘 문제해결전략
- 파이썬
- k번째 답 계산하기
- 비트 마스크
- 카카오
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
31 |
글 보관함