728x90
빈도 정렬
다국어
시간 제한메모리 제한제출정답맞힌 사람정답 비율
1 초 | 128 MB | 5648 | 2765 | 2180 | 49.121% |
문제
위대한 해커 창영이는 모든 암호를 깨는 방법을 발견했다. 그 방법은 빈도를 조사하는 것이다.
창영이는 말할 수 없는 방법을 이용해서 현우가 강산이에게 보내는 메시지를 획득했다. 이 메시지는 숫자 N개로 이루어진 수열이고, 숫자는 모두 C보다 작거나 같다. 창영이는 이 숫자를 자주 등장하는 빈도순대로 정렬하려고 한다.
만약, 수열의 두 수 X와 Y가 있을 때, X가 Y보다 수열에서 많이 등장하는 경우에는 X가 Y보다 앞에 있어야 한다. 만약, 등장하는 횟수가 같다면, 먼저 나온 것이 앞에 있어야 한다.
이렇게 정렬하는 방법을 빈도 정렬이라고 한다.
수열이 주어졌을 때, 빈도 정렬을 하는 프로그램을 작성하시오.
입력
첫째 줄에 메시지의 길이 N과 C가 주어진다. (1 ≤ N ≤ 1,000, 1 ≤ C ≤ 1,000,000,000)
둘째 줄에 메시지 수열이 주어진다.
출력
첫째 줄에 입력으로 주어진 수열을 빈도 정렬한 다음 출력한다.
예제 입력 1 복사
5 2
2 1 2 1 2
예제 출력 1 복사
2 2 2 1 1
예제 입력 2 복사
9 3
1 3 3 3 2 2 2 1 1
예제 출력 2 복사
1 1 1 3 3 3 2 2 2
예제 입력 3 복사
9 77
11 33 11 77 54 11 25 25 33
예제 출력 3 복사
11 11 11 33 33 25 25 77 54
흐름
코드
#include <bits/stdc++.h>
using namespace std;
int n,c,a;
map<int, int> m, ord;
vector<pair<int,int>> v;
bool cmp(pair<int,int> a, pair<int,int> b){
if(a.first==b.first){ //빈도수 같으면
return ord[a.second]<ord[b.second]; //순서 더 작은걸로(먼저 입력된걸로) 저장
}
return a.first> b.first; //빈도수 오름차순
}
int main(){
ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);
//1. 입력받기
cin >> n >> c;
//2. 빈도수, 순서 저장
for(int i=0;i<n;i++){
cin >> a;
m[a]++; //빈도수 저장
if(ord[a]==0) ord[a] = i+1; //순서 저장
}
//3. 빈도수대로 정렬
//3-1. 빈도수 벡터 만들기
for(auto it:m){
v.push_back({it.second, it.first});
}
//3-2. 정렬하기
sort(v.begin(), v.end(), cmp);
//4. 빈도수대로 출력하기
for(auto i:v){
for(int j=0;j<i.first;j++){
cout << i.second << " ";
}
}
}
유의할 점, 팁
- key-value쌍이 필요한데 value로도 정렬할 필요가 있다면 map을 여러개 만들자.
- map은 key가 없다면 기본적으로 0 또는 빈문자열이 할당된다.
- 특별한 조건이 붙는 정렬은 custom 정렬(cmp 정의)을 생각하자.
- 순서 저장시에는 중복을 확인하고 순서를 저장하자.
if(ord[a]==0) ord[a] = i+1; //순서 저장
728x90
'알고리즘 > 알고리즘 문제풀이' 카테고리의 다른 글
2870번: 수학숙제 [C++] (2) | 2023.02.01 |
---|---|
4659번: 비밀번호 발음하기 [C++] (0) | 2023.01.31 |
2828번 사과 담기 게임 [C++] (0) | 2023.01.30 |
1992번: 쿼드트리 [C++] (0) | 2023.01.12 |
2583번: 영역 구하기 [C++] (0) | 2023.01.12 |