백준 5052 - 전화번호 목록
Updated:
Java
5052 번 - 전화번호 목록
문제
접근 방법
입력으로 들어오는 문자열들마다 이전에 다른 문자열이 현재 문자열의 접두어인지 확인해야하는 과정을 거쳐야한다.
길이 순으로 문자열 정렬
먼저, 접두어가 되려면 앞서 나온 문자열들은 현재 문자열의 길이보다 짧거나 같아야 한다.
따라서 Collections.sort()
를 해주어, 길이 순으로 정렬한다.
접두어 비교
이제 짧은 문자열 부타 하나씩 이전 문자열 중에 접두어가 있는지 확인한다.
먼저 생각할 수 있는 방법은, 현재 문자열의 길이를 len
이라고 하면, 1부터 len까지 String.subString
으로 자르면서 이전에 있는 문자열 중 접두어가 될 수 있는 문자열을 찾는다.
하지만 이 방법은 Test Case의 개수 x 총 비교해야할 문자열 개수 : ((1 + n) x (n/2)) / 2 x 전화번호의 최대 길이 10 == 50 x 25002500 x 10
으로 시간초과를 유발한다.
따라서 HastSet을 사용하였는데, HashSet의 Contains
시간 복잡 도는 O(1)이다.
현재 문자열 접두어가 이전에 존재한 문자열에 있는지 Set의 Contains
로 확인한다.
따라서 50 x 10000 x 10
으로 시간 복잡도를 확 줄일 수 있다.
Set 시간 복잡도
Class Name | Add | Contains | Next |
---|---|---|---|
HashSet | O(1) | O(1) | O(h/n) |
LinkedHashSet | O(1) | O(1) | O(1) |
EnumSet | O(1) | O(1) | O(1) |
TreeSet | O(log n) | O(log n) | O(log n) |
코드
import java.util.*;
import java.io.*;
public class Main {
static int tc, result;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
tc = stoi(br.readLine());
boolean isOk = true;
while(tc-- != 0) {
int n = stoi(br.readLine());
List<String> arrS = new ArrayList<>();
for(int i = 0; i < n; i++) {
arrS.add(br.readLine());
}
// 길이 순으로 문자열 정렬
Collections.sort(arrS, (o1, o2)->{
return Integer.compare(o1.length(), o2.length());
});
isOk = true;
Set<String> phone = new HashSet<>();
String str;
for(int idx = 0; idx < n; idx++) {
str = arrS.get(idx);
// 처음 들어온 문자열(제일 짧은)
if(phone.isEmpty()) {
phone.add(str);
continue;
}
for(int i = 1; i <= str.length(); i++) {
// Set에 존재하는 문자열 중에 접두어가 있는지 확인
if(phone.contains(str.substring(0, i))) {
isOk = false;
}
}
phone.add(str);
}
if(isOk)
System.out.println("YES");
else
System.out.println("NO");
}
br.close();
}
static int stoi(String str) {
return Integer.parseInt(str);
}
}
총평
후기
디테일 부족으로 2번 틀린 문제.. 제출하기 전에 조금 더 유심히 봐야할 필요가 있다.