[문제 링크]
문제
화은이는 이번 영어 시험에서 틀린 문제를 바탕으로 영어 단어 암기를 하려고 한다. 그 과정에서 효율적으로 영어 단어를 외우기 위해 영어 단어장을 만들려 하고 있다. 화은이가 만들고자 하는 단어장의 단어 순서는 다음과 같은 우선순위를 차례로 적용하여 만들어진다.
- 자주 나오는 단어일수록 앞에 배치한다.
- 해당 단어의 길이가 길수록 앞에 배치한다.
- 알파벳 사전 순으로 앞에 있는 단어일수록 앞에 배치한다
보다 짧은 길이의 단어의 경우 읽는 것만으로도 외울 수 있기 때문에 길이가 이상인 단어들만 외운다고 한다. 화은이가 괴로운 영단어 암기를 효율적으로 할 수 있도록 단어장을 만들어 주자.
입력
첫째 줄에는 영어 지문에 나오는 단어의 개수 과 외울 단어의 길이 기준이 되는 이 공백으로 구분되어 주어진다. (, )
둘째 줄부터 번째 줄까지 외울 단어를 입력받는다. 이때의 입력은 알파벳 소문자로만 주어지며 단어의 길이는
을 넘지 않는다.
단어장에 단어가 반드시 1개 이상 존재하는 입력만 주어진다.
출력
화은이의 단어장에 들어 있는 단어를 단어장의 앞에 위치한 단어부터 한 줄에 한 단어씩 순서대로 출력한다.
풀이
이미 여러 번 풀어보았던 정렬 문제인데 일반적인 정렬이 아닌 까다로운 정렬 기준을 가진 문제였다.
거기에 더해 시간 제한도 1초로 짧아서 반복문을 여러 번 써가며 정렬을 할 경우 시간초과가 나올 것 같아 꽤 오랜시간 방법을 고민했다.
배열에 넣을 때 비교한 후 맞는 인덱스에 넣기, 각 기준에 맞는 정렬 메소드 만들기 등 여러 시도를 하다가 문득 Comparable Interface를 상속 받은 클래스를 만들고 compareTo() 메소드를 오버라이딩해서 내가 원하는 정렬 기준에 따라 정렬이 가능하다는 사실이 떠올랐다.
그래서 바로 시도해보았고 다행히 시간내에 잘 작동하는 것도 확인할 수 있었다. 그리고 코드를 더 최적화할 방법이 없을까 고민하다가 Comparator Interface를 정의해서 sort의 매개변수로 넘기는 편이 더 깔끔한 코드가 되겠다 생각해서 최종 수정까지 마쳤다.
- 입력 : N과 M을 읽어온 후 N의 값만큼 입력받은 단어 중 길이가 M 이상인 단어만 Map에 빈도와 함께 저장
- List 생성 : Map의 키값을 List로 만듬
- List 정렬 : Collections.sort에 매개변수로 넘기는 Comparator를 정의해서 정렬 기준에 따라 단어를 정렬
- 출력 : 정렬된 List의 순서대로 출력
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. 입력
StringTokenizer st = new StringTokenizer(br.readLine());
int N = Integer.parseInt(st.nextToken());
int M = Integer.parseInt(st.nextToken());
Map<String, Integer> wordCount = new HashMap<>();
for (int i = 0; i < N; i++) {
String input = br.readLine();
//길이가 M이상
if (input.length() >= M) {
wordCount.put(input, wordCount.getOrDefault(input, 0) + 1);
}
}
// 2. List 생성
List<String> words = new ArrayList<>(wordCount.keySet());
// 3. List 정렬
Collections.sort(words, new Comparator<String>() {
public int compare(String word1, String word2) {
int frequency1 = wordCount.get(word1);
int frequency2 = wordCount.get(word2);
// 빈도에 따라 정렬 (내림차순)
if (frequency1 != frequency2) {
return frequency2 - frequency1;
}
// 단어의 길이에 따라 정렬 (내림차순)
if (word1.length() != word2.length()) {
return word2.length() - word1.length();
}
// 사전순 정렬
return word1.compareTo(word2);
}
});
// 4. 출력
for (String word : words) {
bw.write(word + "\n");
}
bw.flush();
bw.close();
br.close();
}
}
'Algorithm > Problem solving' 카테고리의 다른 글
[프로그래머스/Python] 42579 베스트 앨범 (Level 3) (0) | 2025.03.25 |
---|---|
[백준/Java] 2108 통계학 (0) | 2025.03.25 |
[백준/Java] 1010 다리 놓기 (0) | 2025.03.25 |
[백준/Java] 11050 이항 계수 1 (0) | 2025.03.25 |
[백준/Java] 28279 덱2 (0) | 2025.03.25 |