backend/computer science
알고리즘 기초: 그리디 (Greedy) 알고리즘이란? (파이썬코드)
seul chan
2021. 4. 8. 09:08
Greedy algorithm
- 현재 상황에서 지금 당장 좋은것만 고르는 방법
- 문제를 풀기 위한 최소한의 아이디어
- 정당성 분석: 이 방법으로도 문제가 제공하는 최적의 해를 구할 수 있는지
- 일반적인 상황에서 그리디 알고리즘으로는 최적의 해를 보장하지 못할 때가 많음
문제
거스름돈 문제 (500, 100, 50, 10)
정당성 분석
- 큰 단위가 항상 작은 단위의 배수이기 때문에
- 작은 단위의 배수가 아니라면 최적의 해를 보장해주지 못함 (i.e. 500, 400, 100...)
시간복잡도
- 화폐의 개수에 따라 증가하므로
O(K)
(화폐가 K개일때)
n = 1260
count = 0
coins = [500, 100, 50, 10]
for coin in coins:
count += n // coin
n = n % coin
print(count)
나누기/빼기 문제
N이 1이 될 때까지 두 과정 중 하나를 반복적으로 수행
- N에서 1을 뺌
- N을 K로 나눔
N, K가 주어질 때 N이 1이 될 때까지 수행해야 하는 과정의 최소 횟수
N = 26
K = 4
count = 0
# n이 1일때까지 while문
# n 이 k로 나눠떨어지면 N //= K
# 아니라면 N -= K
while N != 1:
if N % K == 0:
N //= K
print(N)
else:
N -= 1
print(N)
count += 1
답안
result = 0
# 시간복잡도를 log(n)으로 줄이기 위해서
while True:
# k로 나누어 떨어지는 값 구해서
target = (n // k) * k
# 1을 빼는 연산회수를 한번에 계산
result += (n - target)
if n < k:
break
result += 1
n //= k
# 마지막으로 남은 수에서 1 빼기 -> 왜?
result += (n - 1)
곱하기 or 더하기 문제
각 자리가 숫자 (0-9)로 이뤄진 문자열 S
왼쪽부터 오른쪽으로 하나씩 모든 숫자 사이에 x, +를 넣어 만들어질 수 있는 가장 큰 수
(단, 모든 연산은 왼쪽에서 순서대로 이루어진다고 가정. x 가 + 보다 먼저 되지 않음.)
# 0이 아니라면 무조건 곱하는게 크고, 0이라면 더하기
s = '02984'
result = 0
for i in s:
num = int(i)
# i가 0이거나 기존 값이 0일때는 무조건 더하기
if num == 0 or result == 0:
result += num
# 아니라면 x
else:
result *= num
답안
# 두 숫자 중에 하나라도 '0', '1'인 경우 더해야됨
s = '02148'
result = int(s[0])
for i in range(1, len(s)):
num = int(s[i])
if num <= 1 or result <= 1:
result += num
else:
result *= num
모험가 길드 문제
공포도가 X인 모험가는 반드시 X명 이상으로 구성한 모험가 그룹에 참가해야됨.
만들 수 있는 가장 많은 모험가 그룹은?
N = 5, 공포도=[2, 3, 1, 2, 2]
# 가장 작은 모험가부터 출발시키면 됨
# 정렬한 다음
n = 5
fear = [2, 3, 1, 2, 2]
result = 0
count = 0
fear.sort()
for i in fear:
# 모인 모험가 수가 현재 모험가 공포도보다 크면 출발
print(i)
if i == 1:
result += 1
elif i <= count:
result += 1
# 아니면 모험가 필요 count 증가
else:
count += 1
print(result)
답안
n = 5
fear = [2, 3, 1, 2, 2]
fear.sort()
result = 0
count = 0
for i in fear:
count += 1
if count >= i:
result += 1
count = 0