탐욕 알고리즘(Greedy algorithm)은 최적해를 구하는 데에 사용되는 근사적인 방법으로, 여러 경우 중 하나를 결정해야 할 때마다 그 순간에 최적이라고 생각되는 것을 선택해 나가는 방식으로 진행하여 최종적인 해답에 도달한다.
https://ko.wikipedia.org/wiki/%ED%83%90%EC%9A%95_%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98
탐욕 알고리즘이 잘 작동하는 문제는 대부분 탐욕스런 선택 조건(greedy choice property)과 최적 부분 구조 조건(optimal substructure)이라는 두 가지 조건이 만족된다. 탐욕스런 선택 조건은 앞의 선택이 이후의 선택에 영향을 주지 않는다는 것이며, 최적 부분 구조 조건은 문제에 대한 최적해가 부분문제에 대해서도 역시 최적해라는 것이다.
이러한 조건이 성립하지 않는 경우에는 탐욕 알고리즘은 최적해를 구하지 못한다. 하지만, 이러한 경우에도 탐욕 알고리즘은 근사 알고리즘으로 사용이 가능할 수 있으며, 대부분의 경우 계산 속도가 빠르기 때문에 실용적으로 사용할 수 있다. 이 경우 역시 어느 정도까지 최적해에 가까운 해를 구할 수 있는지를 보장하려면 엄밀한 증명이 필요하다.
어떤 특별한 구조가 있는 문제에 대해서는 탐욕 알고리즘이 언제나 최적해를 찾아낼 수 있다. 이 구조를 매트로이드라 한다. 매트로이드는 모든 문제에서 나타나는 것은 아니나, 여러 곳에서 발견되기 때문에 탐욕 알고리즘의 활용도를 높여 준다.
프로그래머스 LV1. 체육복 과 Leetcode의 455. Assign Cookies
프로그래머스 Lv1. 체육복 : https://school.programmers.co.kr/learn/courses/30/lessons/42862
def solution(n, lost, reserve):
set_lost = set(lost) - set(reserve)
set_reserve = set(reserve) - set(lost)
for i in set_reserve:
if i-1 in set_lost:
set_lost.remove(i-1)
elif i+1 in set_lost:
set_lost.remove(i+1)
return n - len(set_lost)
Leetcode 455. Assign Cookies : https://leetcode.com/problems/assign-cookies/
class Solution:
def findContentChildren(self, g: List[int], s: List[int]) -> int:
g.sort()
s.sort()
i,j = 0,0
ans = 0
while i<len(g) and j<len(s):
if g[i] <= s[i]:
ans +=1
i+=1
j+=1
return ans
프로그래머스 큰 수 만들기 와 Leetcode 402. Remove K Digits
프로그래머스 Lv2. 큰 수 만들기: https://school.programmers.co.kr/learn/courses/30/lessons/42883
def solution(number, k):
stack = []
for n in number:
while k>0 and stack and stack[-1] < n:
stack.pop()
k-=1
stack.append(n)
while k>0:
stack.pop()
k-=1
answer = ''.join(stack)
if not answer:
return '0'
return answer
Leetcode 402. Remove K Digits :
https://leetcode.com/problems/remove-k-digits/
class Solution:
def removeKdigits(self, num: str, k: int) -> str:
stack = []
for n in num:
while k>0 and stack and stack[-1] > n:
stack.pop()
k-=1
stack.append(n)
while k>0:
stack.pop()
k-=1
result = ''.join(stack).lstrip('0')
if not result:
return '0'
return result
프로그래머스 구명보트 와 Leetcode 881. Boats to Save People
프로그래머스 Lv2. 구명보트:
https://school.programmers.co.kr/learn/courses/30/lessons/42885
def solution(people, limit):
l, r = 0, len(people)-1
answer = 0
people.sort()
while l<=r:
if people[l] + people[r] <= limit:
l+=1
r-=1
answer +=1
return answer
보트의 최대 수용 인원을 고려하여 사람들을 정렬하는데, 보트에 최대한 많은 사람을 태우기 위해서는 무거운 사람과 가벼운 사람을 함께 태워야 한다. 따라서 몸무게를 기준으로 오름차순으로 정렬한다.
그리고 나서 그리디 알고리즘을 사용하여 각 단계에서 가장 최적의 선택을 진행한다. 이 경우에는 가장 무거운 사람과 가장 가벼운 사람을 함께 보트에 태우되, 보트의 최대 수용 인원을 초과하지 않도록 이진 탐색을 사용해서 가장 가벼운 사람, 가장 무거운 사람의 포인트를 옮겨가면서, 무게가 초과되면 보트를 하나 띄워보내고, 그다음 무거운사람과 가벼운사람을 매칭해가면서 푼다.
Leetcode 881. Boats to Save People :
https://leetcode.com/problems/boats-to-save-people/
class Solution:
def numRescueBoats(self, people: List[int], limit: int) -> int:
people.sort()
l,r = 0, len(people)-1
ans = 0
while l<=r:
if people[l] + people[r] <=limit:
l+=1
r-=1
ans +=1
return ans
두 문제 그리디이면서 이진탐색을 사용해서 해결한다.
프로그래머스 조이스틱과 Leetcode 1541. Minimum Insertions to Balance a Parentheses String
프로그래머스 조이스틱:
https://school.programmers.co.kr/learn/courses/30/lessons/42860
코드를 입력하세요
Leetcode 1541. Minimum Insertions to Balance a Parentheses String :
https://leetcode.com/problems/minimum-insertions-to-balance-a-parentheses-string/
왼쪽 괄호 '('에는 해당하는 두 개의 연속 오른쪽 괄호 '))'가 있어야 합니다.
왼쪽 괄호 '('는 해당하는 두 개의 연속된 오른쪽 괄호 '))' 앞에 와야 합니다.
즉, '('를 여는 괄호로, '))'를 닫는 괄호로 처리합니다.
예를 들어, "())", "())(())))" 및 "(())())))"는 균형을 이루고 ")()", "()))" 및 "( ()))"의 균형이 맞지 않습니다.
필요한 경우 균형을 맞추기 위해 문자열의 어느 위치에나 '(' 및 ')' 문자를 삽입할 수 있습니다.
s를 균형 있게 만드는 데 필요한 최소 삽입 수를 반환합니다.
class Solution:
def minInsertions(self, s: str) -> int:
ans, closed = 0,0
for c in s:
if c == '(':
if closed%2==1:
closed -=1
ans+=1
closed+=2
else:
closed-=1
if closed <0:
ans+=1
closed+=2
return ans+ closed
필요한 왼쪽 괄호 opened, 오른쪽 괄호 closed라고 할 때, 주어진 문자열을 탐색하면서
문자열이 '(' 일 때
만약 close가 홀수이면, 쌍을 이루는 )가 하나 더 필요한 상태이다. 그러므로 close를 하나 줄이고, 삽입 횟수 ans를 하나 증가시킨다.
그리고 close에 2를 더해주는데, 이는 쌍을 이루는 )가 두 개 추가로 필요하다는 것을 의미한다.
문자열이 '(' 일 때, close를 하나 줄인다. 이는 쌍을 이루는 (가 하나 출현했다는 것을 의미한다.
만약 close가 음수이면, 쌍을 이루는 (가 부족한 상태이다. 이 경우, close를 다시 2만큼 더해주고, 삽입 횟수 ans를 하나 증가시킵니다.
마지막으로, close와 ans를 합하여 최종 결과를 반환한다.
프로그래머스 섬 연결하기와
프로그래머스 섬 연결하기:
코드를 입력하세요
Leetcode
코드를 입력하세요
프로그래머스 단속카메라와
프로그래머스 단속카메라:
코드를 입력하세요
Leetcode
코드를 입력하세요