문제는
https://www.acmicpc.net/problem/20920
다음과 같고,
구현 + 정렬 문제인것같다.
나는 정렬 문제를 풀며 약간 외우다시피 했는데,
우리가 아는 알파벳 사전순
숫자 오름차순을 구현하려면
이러한 내용들은 보통 compareTo에서 this 가 먼저 나온다
즉, 아래와 같이 구현하면 된다는 이야기.
//오름차순으로 구현하려면 if 안에서 this를 먼저 써야한다는 말.
if(this.숫자값 > 매개변수.숫자값) return 1;
return -1;
//혹은
return this.숫자값 - 매개변수.숫자값;
아래는 약간 다른데, 우선순위 큐에서는 다익스트라를 생각해보자.
위와 같이 구현하면, 다익스트라에서는 최솟값을 먼저 우선순위로 두고 뽑는다.
그럼 위와 반대로 구현하면, 값이 큰 내용부터 뽑겠네..?
라고 생각하고 풀었다.
먼저 뽑히기 위해서는
1번 우선순위는 자주 나올수록 큐 우선순위가 높다 = 숫자 times가 클수록 먼저 뽑힌다
2번 우선순위는 단어의 길이가 길수록 큐 우선순위가 높다 = String의 length()가 클수록 먼저 뽑힌다.
3번 사전순
public int compareTo (wordBook e) {
if(this.times == e.times) {
if(this.word.length() == e.word.length()) {
return this.word.compareTo(e.word); //3번 우선순위 알파벳 사전 순
}
else {
return e.word.length() - this.word.length(); //2번 우선순위, 길수록 큐 우선순위
}
}
return e.times - this.times; //1번 우선순위 자주나올수록 큐 우선순위 (times 클수록)
}
풀이는 아래와 같다.
각각 주석에 헷갈릴 내용을 설명해놓았다.
import java.io.*;
import java.util.*;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
//우선순위
//1. 자주 나오는 단어일수록 앞에 배치한다. (횟수에 따라 정렬)
//2. 해당 단어의 길이가 길수록 앞에 배치한다. (횟수같으면 length() 따라 정렬)
//3. 알파벳 사전 순으로 앞에 있는 단어일수록 앞에 배치한다 (length() 같으면 기존의 String compareTo에 따라 정렬)
//첫줄 단어 개수와 제한 길이.
StringTokenizer st1 = new StringTokenizer(br.readLine());
int N = Integer.parseInt(st1.nextToken()); //단어 개수
int M = Integer.parseInt(st1.nextToken()); //제한 길이
PriorityQueue<wordBook> q = new PriorityQueue<>(); //map을 순회하며 넣어줄 우선순위 Queue
HashMap<String, Integer> map = new HashMap<>(); //단어를 읽으면서, 해당 단어가 몇번 나왔는지와 함께 저장해줄 map
for(int i = 0 ; i < N ; i++) {
String word = br.readLine();
if(word.length() < M) { //길이 제한 안맞다면, 제끼고
continue;
}
else { //길이 제한 충족할때는
if(map.containsKey(word)) { //이미 존재하면 갯수 +1 해주고
map.replace(word, map.get(word)+1);
}
else { //존재하지 않으면 map에 넣어주기
map.put(word, 1);
}
}
}
// 여기까지 오면 map 에 단어와 그 단어의 횟수가 저장됨. 이제 순회하며 해당 내용을 우선순위 큐에 넣을 예정.
for(Map.Entry<String, Integer> now : map.entrySet()) {
q.add(new wordBook(now.getKey(), now.getValue()));
}
//우선순위 큐이기에, 아래에 작성한 매서드대로 정렬해주니까, Queue의 내용을 뽑아내며 출력하면 된다.
while(!q.isEmpty()) {
bw.write(q.poll().word + "\n");
}
bw.flush();
bw.close();
}
static class wordBook implements Comparable<wordBook>{
String word;
int times;
public wordBook (String word, int times) {
this.word = word;
this.times = times;
}
public int compareTo (wordBook e) {
if(this.times == e.times) {
if(this.word.length() == e.word.length()) {
return this.word.compareTo(e.word); //3번 우선순위
}
else {
return e.word.length() - this.word.length(); //2번 우선순위, 길수록 큐 우선순위
}
}
return e.times - this.times; //1번 우선순위 자주나올수록 큐 우선순위 (times 클수록)
}
}
}
아쉬웠던 점은, 큐에 넣으면, 해당 값 꺼내와서 수정하는 로직을 잘 모르겠어서, 따로 해쉬맵<String, Integer>을 만들어서 해당 단어 나올때마다 Integer++; 해주기까지 생각이 좀 시간이 걸렸다는게 아쉽다.
또 새로 안 사실은, 아래를 통해 map을 순회할 수 있다.
for(Map.Entry<String, Integer> now : map.entrySet()) {
q.add(new wordBook(now.getKey(), now.getValue()));
}