[알고리즘] 코테 유형 분석 2. 우선 순위 큐

최민길(Gale)·2023년 7월 10일
1

알고리즘

목록 보기
95/172

안녕하세요 이번 시간에는 우선 순위 큐 문제 유형을 확인하며 어떻게 적용시켜야 하는지에 대해 포스팅해보도록 하겠습니다.

우선 첫 번째 유형은 정렬을 사용해야 하지만 배열이나 리스트를 사용하면 안되는 문제입니다. 주로 배열이나 리스트를 정렬했을 경우 시간 초과가 발생하고 중간 인덱스를 탐색할 필요가 없는 문제들입니다. 이 문제들을 우선 순위 큐의 정렬 특성을 이용하여 배열이나 리스트를 정렬 시 소요되는 시간을 감소시킬 수 있습니다. 또한 자바의 경우 우선 순위 큐 또는 큐에 넣을 클래스에 Comparable<T> 또는 Comparator<T> 인터페이스를 오버라이딩하여 원하는 정렬 조건을 커스텀할 수 있습니다.

Comparable<T>와 Comparator<T>는 둘 다 객체의 정렬에 사용되는 인터페이스이지만 약간의 차이가 존재합니다. Comparable<T>의 경우 public int compareTo(T o) 메서드를 구현하여 자신과 다른 객체들에 대한 비교를 진행합니다. 하지만 Comparator<T>의 경우 public int compare(T o1, T o2) 메서드를 이용하여 파라미터로 받은 두 객체를 비교하여 결과를 반환합니다. 쉽게 말해 클래스가 피연산자처럼 동작하는 클래스의 경우 Comparable<T>를 구현하여 다른 자료구조에서 정렬 시 기준대로 정렬되도록 하고, 클래스가 연산자처럼 동작하는 클래스의 경우 Comparator<T>를 구현하여 다른 자료구조를 기준에 맞게 정렬할 때 사용하면 좋습니다.

백준 11286(절댓값 힙) 문제는 배열에 정수를 넣고 입력이 오면 절댓값이 가장 작은 값, 절댓값이 같다면 가장 작은 값을 출력하는 문제입니다. 우선 순위 큐에 Comparator<T>를 추가하여 조건에 맞게 정렬하거나 우선 순위 큐에 저장되는 클래스를 Comparable<T>를 오버라이딩하여 조건을 추가하여 진행하면 됩니다.

백준 2075(N번째 큰 수) 문제는 표 내에서 N번째 큰 수를 찾는 문제입니다. 표의 값들을 우선 순위 큐에 저장한 후 큐의 사이즈가 N보다 크다면 poll하는 방식으로 구현합니다.

백준 1715(카드 정렬하기) 문제는 카드 묶음의 최소 비교 횟수를 구하는 문제입니다. 그리디 방식으로 오름차순으로 정렬된 우선 순위 큐에 데이터를 추가한 후 두 개를 뽑아 그 합을 다시 우선 순위 큐에 저장하여 큐의 사이즈가 1이 될때까지 진행합니다.

두 번째 유형은 중간값을 구하는 문제입니다. 중간값의 특성상 수열이 정렬이 되어있어야 하고 항상 가운데를 가리키기 때문에 중간값 기준 작은 수를 담는 우선 순위 큐와 큰 수를 담는 우선 순위 큐 2개를 만들어 작은 큐는 내림차순, 큰 큐를 오름차순 정렬을 합니다. 이렇게 되면 저번 포스팅의 스택의 "커서를 활용하는 문제"처럼 현재 값 기준으로 좌우에 정렬된 값들을 얻을 수 있어 중간값을 구할 수 있습니다. 여기서 주의할 점은 두 큐의 차이가 1 이하로 계속 유지되어야 한다는 점입니다. 두 값이 1보다 크게 된다면 중간값이 아니라 이상한 부분을 참조하게 되어 오류가 발생합니다.

백준 1655(가운데를 말해요) 문제와 2696(중앙값 구하기)가 대표적인 문제입니다. 주어진 입력을 중간값 기준 작은 수와 큰 수를 담는 우선 순위 큐에 각각 저장하고 기준으로 한 큐를 1 더 크게 하여 데이터를 추가합니다. 이 때 중간값 구하는 로직을 수행한 후 기준으로 한 큐의 피크값을 출력하면 됩니다.

profile
저는 상황에 맞는 최적의 솔루션을 깊고 정확한 개념의 이해를 통한 다양한 방식으로 해결해오면서 지난 3년 동안 신규 서비스를 20만 회원 서비스로 성장시킨 Software Developer 최민길입니다.

0개의 댓글