이동식 저장소

2696. 중앙값 구하기 본문

Problem Solving/BOJ

2696. 중앙값 구하기

해스끼 2021. 5. 24. 23:10

오랜만에 문제를 풀었다. 그동안 생각이 좀 많았어서 ㅎㅎ..

 

2696번: 중앙값 구하기

첫째 줄에 테스트 케이스의 개수 T(1 ≤ T ≤ 1,000)가 주어진다. 각 테스트 케이스의 첫째 줄에는 수열의 크기 M(1 ≤ M ≤ 9999, M은 홀수)이 주어지고, 그 다음 줄부터 이 수열의 원소가 차례대로 주

www.acmicpc.net


너무 쉬워

그냥 매번 입력받으면서 정렬하면 그만 아닌가?

맞겠냐

한번 입력받고 정렬하는 데 대략 $MlogM$, 입력을 총 $M$번 받으므로 테스트 케이스 하나당 시간 복잡도는 $O(M^{2}logM)$이다. 테스트 케이스의 개수까지 고려하면 풀릴 리가 없다.

그럼 어쩔까요

당연히 더 효율적인 방법을 찾아야 한다. 사실 이 문제처럼 변하는 배열에서 중앙값을 구하고 싶을 때 유용한 테크닉이 있다. 우선순위 큐를 활용하는 방법이다.

 

우선순위 큐 2개를 준비한다. 하나(``left``)는 큰 수가 위로 오도록, 다른 하나(``right``)는 작은 수가 위로 가도록 정렬한다. 이름에서 알 수 있듯이 ``left``와 ``right``의 원소를 순서대로 쭉 이으면 하나의 정렬된 배열이 된다. 그러니까 대략 이런 식이다.

``size(left) = size(right) + 1``이라는 조건을 두면 중앙값을 ``left.top()``으로 쉽게 찾을 수 있다. 물론 ``right``의 크기를 더 크게 해도 된다. 이 경우 중앙값은 ``right.top()``이 된다.

 

이제 수를 하나씩 입력받으면서 조건에 맞게 ``left``와 ``right``를 조절하면 된다. 나는 우선 ``right``에 넣은 다음 ``size(left) = size(right) + 1``를 만족하도록 push와 pop 연산을 적용했다.


4ms?

사실 이 방법의 시간복잡도는  최악의 경우 $O(M^{2})$(오름차순 또는 내림차순으로 정렬된 배열이 주어지는 경우)이지만 통과되는 걸 보니 이 풀이가 맞는 모양. 

 

이 테크닉을 잘 기억하도록 하자.

'Problem Solving > BOJ' 카테고리의 다른 글

10800. 컬러볼  (0) 2021.07.21
1507. 궁금한 민호  (0) 2021.06.26
15824. 너 봄에는 캡사이신이 맛있단다  (0) 2021.04.23
2560. 짚신벌레  (0) 2021.04.17
16637. 괄호 추가하기  (0) 2021.04.17
Comments