탐욕 알고리즘 (Greedy)
Greedy는 직역하면 "탐욕스러운, 욕심이 많은"이라는 뜻이다.
탐욕 알고리즘(Greedy Algorithm)은 당장 퇴적의 상황만을 채택하여 최종적인 결과를 내는 알고리즘이다.
탐욕 알고리즘으로 문제를 해결하는 방법으로는 다음과 같이 3 단계가 있다.
- 선택 절차 : 현제 상태에서 최적의 해답을 선택
- 적절성 검사 : 선택된 값이 문제의 조건을 만족하는지 검사
- 해답 검사 : 원래 문제가 해결되었는지 검사, 미해결 시 선택 절차(1번)으로 돌아가 위의 과정을 반복
글로 쓰니까 모르겠는데? 할 수 있다.
사실 우리가 실생활에서 그리드 알고리즘은 종종 사용했다.
바로 동전 거슬러 줄때 사용한다.
편의점에서 일하든, 마트에서 일하든 거스름돈을 줄 때 가장 적은 동전을 활용해 잔돈을 지불해야 나중에 동전이 부족하지 않다.
예를 들어서 만원으로 4320원 짜리 물건을 사서 5680원을 거슬러 줄 때
거스름돈 이하의 화폐중에서 가장 큰 단위 - 5천원
가장 큰 단위를 뺀 나머지 - 680원 (5천원 한장)
또 남은 거스름돈 이하의 화폐 중에서 가장 큰 단위 - 500원
가장 큰 단위를 뺀 나머지 - 180원 (500원짜리 하나)
또또 남은 거스름돈 이하의 화폐 중에서 가장 큰 단위 - 100원
가장 큰 단위를 뺀 나머지 - 80원 (100원짜리 하나)
또또또 남은 거스름돈 이하의 화폐 중에서 가장 큰 단위 - 50원
가장 큰 단위를 뺀 나머지 - 30원 (50원짜리 하나)
또또또또 남은 거스름돈 이하의 화폐 중에서 가장 큰 단위 - 10원
나머지 30원은 10원짜리 3개로 해결
총 5천원 한장 , 500원 하나, 100원 하나, 50원 하나, 10원짜리 3개로 해결!
-> 가장 적은 짤짤이로 거스름돈에 맞추었다.
여기서 위의 3 단계를 대입하여 말하면
선택 절차 : 가장 큰 단위의 화폐를 선택
(적은 화폐의 갯수로 조건을 충족시키기 위해) / 5천원부터 사용
적절성 검사 : 내가 선택한 화폐가 거스름돈을 넘지 않는지 검사
(5천원 2장은 거스름돈을 넘고, 한장은 안넘으니까 한장 주고 밑의 단위 화폐로 줘야 함)
해답검사 : 선택된 화폐들의 합이 거스름돈을 넘어가는지 검사하고, (5천원, 500원, 100원 ... 짤짤이 다 합해서) 넘으면 다시 처음부터 다시, 딱 맞으면 끝 -> 거스름돈을 올바르게 줫는지 검사한 것
그런데, 만약 10원짜리가 딱 하나 있어서 하나 밖에 쓸 수 없다면?
우리는 거스름돈 5680원 중 5660원으로 20원 부족하게 거슬러 주거나
50원짜리를 하나 더 써서 5710원으로 30원 더 주어야 한다.
-> 최적의 값으로 줄 수 없다!
이러한 상황이 발생 하기 때문에 탐욕 알고리즘을 적용하기위해서는 두 가지 조건이 따라 붙어야 최적의 값이 나온다.
- 탐욕적 선택 속성 : 앞의 선택이 이후의 선택에 영향을 주지 않아야 함
- 최적 부분 구조 : 문제에 대한 최종 해결 방법은 부분 문제에 대한 최적 문제 해결방법으로 구성됨
(마지막 10원짜리로 해결 가능한 부분인데(부분적 문제), 하나밖에 없으면 -> 해결 안됨, 그런데 여러개 있으면 10원짜리 여러개 주는거로 해결 가능 -> 부분적 문제 해결 가능)
위의 두 조건을 만족하지 않으면 탐욕 알고리즘은 최적의 답을 구하는데 적합하지 않다.
하지만, "최적(5680원)"이 아닌 것이지, "최적에 가까운 (5660원, 5710원)"값을 구할때는 빠르게 구할 수 잇는 알고리즘이 될 수 있다.
이러한 특성으로 탐욕 알고리즘은 근사 알고리즘으로 사용할 수 있다.
'백엔드 > JAVA_코딩테스트' 카테고리의 다른 글
JAVA_코딩테스트 준비_ 알고리즘, 의사코드 (1) | 2022.11.28 |
---|---|
JAVA_코딩테스트 준비_이진 탐색 알고리즘 (Binary Search Algorithm) (0) | 2022.11.28 |
JAVA_코딩테스트 준비_완전 탐색 알고리즘 (부르트포스 / Brute-Force Algorithm) (1) | 2022.11.28 |
JAVA_코딩테스트 준비_(구현/시뮬레이션) (1) | 2022.11.28 |
JAVA_코딩테스트 준비_탐색 알고리즘_(BFS/DFS) (0) | 2022.11.28 |