알고리즘

백준 1655: 가운데를 말해요 [C++]

avocado8 2024. 7. 26. 23:15

https://www.acmicpc.net/problem/1655

 

부른 수들 중에서 중간값을 찾아내야 한다. 짝수개면 둘 중 더 작은거

무작위로 부른 수들의 정렬이 필요하니 우선순위 큐를 사용해야 함을  생각할 수 있다.

 

예시인 1, 5, 2, 10, -99, 7, 5 을 생각해보면

크기순 정렬하면 -99, 1, 2, 5, 5, 7, 10이 되고 중간은 5가 된다.

이걸 왼쪽(작은값들)과 오른쪽(큰값들)으로 나눠서 생각해보자. 이러는 이유는 우선순위큐에서 우리가 쓸 수 있는 값은 어쨌든 top값밖에 없기 때문이다. 중간에 든 걸 뺄 수가 없는 구조니까 우린 중간값이 top에 오도록 만들어주는 편이 좋다.

그렇다면 왼쪽(작은값들)은 내림차순(최대히프)으로,

오른쪽(큰값들)은 오름차순(최소히프)으로 정렬해준다면, 각 부분에서 top이 중간값이 될 수 있을 것이다.

 

중간값을 최대힙에 저장한다치고 구현을 해보자. 그러려면 최대힙의 사이즈가 최소힙보다 같거나 1 더 커야 할 것이다.

수를 입력받고, 윗줄 조건을 만족하는 선에서 힙에 입력받은 수를 푸시한다.

단 이때는 개수 기준으로 저장되므로 입력받은 값이 잘못 저장될 수도 있다. 이를 맞추기 위해 balance라는 함수를 만들어주자.

void balance(priority_queue<int>&max_pq,priority_queue<int, vector<int>, greater<>>&min_pq){
    int max_top = max_pq.top();
    int min_top = min_pq.top();
    
    //작은값들은 최대히프, 큰값들은 최소히프에 저장되어야 함
    if(max_top > min_top){
        //즉 현재 최대히프의 top이 최소히프의 top보다 크다면, 자리를 바꿔주어야 함
        max_pq.pop();
        min_pq.pop();
        
        min_pq.push(max_top);
        max_pq.push(min_top);
    }
}

 

전체 코드

런타임 오류가 한번 났는데, balance를 실행할 때 조건을 주지 않아서였다.

balance는 두 큐의 top값을 보고 실행하는 함수이므로 큐가 비어있다면 실행할 수 없다.

#include <iostream>
#include <queue>

using namespace std;

void balance(priority_queue<int>&max_pq,priority_queue<int, vector<int>, greater<>>&min_pq){
    int max_top = max_pq.top();
    int min_top = min_pq.top();
    
    //작은값들은 최대히프, 큰값들은 최소히프에 저장되어야 함
    if(max_top > min_top){
        //즉 현재 최대히프의 top이 최소히프의 top보다 크다면, 자리를 바꿔주어야 함
        max_pq.pop();
        min_pq.pop();
        
        min_pq.push(max_top);
        max_pq.push(min_top);
    }
}

int main()
{
    ios::sync_with_stdio(false);
	cin.tie(NULL); cout.tie(NULL);
	
    int n, num;
    cin >> n;
    
    priority_queue<int> max_pq;
    priority_queue<int, vector<int>, greater<>> min_pq;
    
    while(n--){
        cin >> num;
        
        if(max_pq.size() > min_pq.size()) {
            //같거나, 최대히프가 하나 더 많도록
            //즉 현재 최대히프사이즈가 더 크다면, 최소히프에 저장해 개수를 맞춰줌
            min_pq.push(num);
        } else {
            max_pq.push(num);
        }
        
        if(!max_pq.empty() && !min_pq.empty()){
            balance(max_pq, min_pq);
        }
        
        //최대히프 top이 중간값이므로 출력
        cout << max_pq.top() << '\n'; 
    }
    
    return 0;
}

 

 

 

'알고리즘' 카테고리의 다른 글

프로그래머스: 베스트앨범 [C++]  (0) 2025.01.03
백준 1629: 곱셈 [C++]  (1) 2024.11.02
백준 1052: 물병 [C++]  (0) 2024.07.25
백준 1043: 거짓말 [C++]  (2) 2024.07.24
백준 1260: DFS와 BFS [C++]  (0) 2024.07.19