Programming/알고리즘 & 코테

[그리디] 큰 수의 법칙 (실전문제, 이것이 코딩테스트다 with 파이썬)

kk_______yy 2023. 12. 8. 17:05

그리디 알고리즘

  • 현재 상황에서 지금 당장 좋은 것만 고르는 방법
  • 암기하지 않아도 풀 수 있는 가능성이 높은 문제 유형
  • 유형이 매우 다양하여 암기해도 풀기 쉽지 않은 문제 유형

 

문제

 

풀이1 : 기본적인 풀이

# 변수 : N 숫자 개수, M 더하는 횟수, K 연속 횟수, result 합
# N, M, K를 공백으로 구분하여 입력받기
n, m, k = map(int, input().split())
result = 0

# N개의 수를 공백으로 구분하여 입력받기
data = list(map(int, input().split()))

data.sort() # 입력받은 수들 정렬
first = data[n-1] # 가장 큰 수
second = data[n-2] # 두 번째로 큰 수

while True: # 무한 루프
    for i in range(k): # 가장 큰 수를 K번 더하기
        if m == 0: # M이 0이라면 반복문 탈출
            break
        result += first
        m -= 1 # 더할 때마다 1씩 빼기
    if m == 0 # M이 0이라면 반복문 탈출
        break
    result += second # 두 번째로 큰 수를 한 번 더하기
    m -= 1 # 더할 때마다 1씩 빼기
    
print(result) # 최종 답안 출력

 

해석

변수 : N 숫자 개수, M 더하는 횟수, K 연속 횟수, result 합

 

1. 입력받은 수를 내림차순으로 정렬 : 큰 수가 앞으로 오도록

2. 가장 큰 수를 K번 더하고, M의 횟수 차감

3. 두번째로 큰 수를 K+1번째에 1번 더하고, M의 횟수 차감

4. M == 0 이 되면 끝

 

한계점 : M의 크기가 100억 이상으로 커지면  O(N)의 시간 복잡도로 인해 시간 초과 판정 위험

 

cf) 시간 복잡도

  • N의 범위가 500인 경우 : 시간 복잡도가 O(N^3)인 알고리즘 설계
  • N의 범위가 2,000인 경우 : 시간 복잡도가 O(N^2)인 알고리즘 설계
  • N의 범위가 100,000(10만)인 경우 : 시간 복잡도가 O(NlogN)인 알고리즘 설계
  • N의 범위가 10,000,000(1000만)인 경우 : 시간 복잡도가 O(N)인 알고리즘 설계

 

풀이2 : 시간 복잡도를 줄인 버전

# 변수 : N 숫자 개수, M 더하는 횟수, K 연속 횟수, result 합
# N, M, K를 공백으로 구분하여 입력받기
n, m, k = map(int, input().split())
result = 0

# N개의 수를 공백으로 구분하여 입력받기
data = list(map(int, input().split()))

data.sort() # 입력받은 수들 정렬
first = data[n-1] # 가장 큰 수
second = data[n-2] # 두 번째로 큰 수

# 가장 큰 수가 더해지는 횟수 계산
count = int(m/(k+1)) * k 
count += m % (k+1)

result = 0
result += (count) * first # 가장 큰 수 더하기
result += (m - count) * second # 두 번째로 큰 수 더하기

print(result) # 최종 답안 출력

 

해석

변수 : N 숫자 개수, M 더하는 횟수, K 연속 횟수, result 합

 

1. 입력받은 수를 내림차순으로 정렬 : 큰 수가 앞으로 오도록

2. 한번에 가장 큰 수가 더해지는 횟수(count)를 계산 : 알고리즘 참고

3. 가장 큰 수를 count 만큼 더함

4. 두번째로 큰 수를 m-count 만큼 더함