https://programmers.co.kr/learn/courses/30/lessons/42577
솔직히 단순하게 전부 돌려가면서 비교하는 방법이 먼저 생각났는데, O(n^2)의 시간복잡도록 시간초과가 날 것 같아 다른 방법을 생각하게 되었다.
문자열 첫 글자에 대한, ArrayList 타입의 배열을 만들고 사전처럼 첫 번째 숫자를 통해 찾아가서 쭉 비교해보는 방법을 택하게 되었다.
import java.util.*;
class Solution {
public boolean solution(String[] phone_book) {
boolean answer = true;
ArrayList<String>[] dictionary = new ArrayList[10];
for (int i = 0; i < dictionary.length; i++) {
dictionary[i] = new ArrayList();
}
for (int i = 0; i < phone_book.length; i++) {
String book = phone_book[i];
int start = book.charAt(0) - '0';
for (int j = 0; j < dictionary[start].size(); j++) {
String str = dictionary[start].get(j);
String target;
if (book.length() > str.length()) {
// 들어오는 문자열이 더 길 경우
target = book.substring(0, str.length());
if (target.equals(str)) {
answer = false;
return answer;
}
} else {
// 기존 리스트의 문자열이 더 길 경우
target = str.substring(0, book.length());
if (target.equals(book)) {
answer = false;
return answer;
}
}
}
dictionary[start].add(book);
}
return answer;
}
}
정확성 측면에서는 모든 테스트케이스가 성공했지만 효율성 측면에서는 몇 개의 테스트케이스에서 시간초과가 났다. 생각해보니 입력 문자열 배열의 각 문자열의 맨 앞에 오는 숫자가 전부 같으면 O(n^2)로 시간 복잡도가 같은 것이다. 아니, 시간 복잡도만 같지 위에서 완전 처음에 떠올렸던 방법보다 더 안좋은 경우가 발생할 것이다.
해시맵을 이용한 방법이다.
접근 계기
제한 사항이 다음과 같을 때 이 방법을 사용하면 최악의 경우 1000000 * 20 * (배열 정렬하는데 걸리는 시간) 정도로 위의 방법의 최악의 경우(1000000 * 1000000) 보다는 훨씬 낫지 않을까 생각하였다.
import java.util.*;
class MyComparator implements Comparator<String> {
@Override
public int compare(String s1, String s2) {
int l1 = s1.length();
int l2 = s2.length();
return l2 - l1;
}
}
class Solution {
public boolean solution(String[] phone_book) {
boolean answer = true;
Map<String, Integer> map = new HashMap<>();
Arrays.sort(phone_book, new MyComparator());
for (int i = 0; i < phone_book.length; i++) {
String book = phone_book[i];
if (i > 0 && map.containsKey(book)) {
answer = false;
break;
}
for (int j = 0; j < book.length(); j++) {
map.put(book.substring(0, j + 1), 0);
}
}
return answer;
}
}