📝 문제

https://programmers.co.kr/learn/courses/30/lessons/42577?language=java

🎯 풀이

문제 분류는 Hash로 분류되어 있지만, 자바는 Hash없이 처리가 가능하다.

자바의 String 클래스는 접두사와 접미사 관련 메소드를 지원한다.
startWithendWith이 그 주인공이다.
좋은 메소드를 제공하는데 굳이 어렵게 구현할 필요는 없다.
바로 사용해보자.

❌ i -> j만 비교

class Solution {
    public boolean solution(String[] phone_book) {
        for(int i = 0; i < phone_book.length-1; i++){
            for(int j = i+1; j < phone_book.length; j++){
                if(phone_book[j].startsWith(phone_book[i])) return false;
            }
        }
        return true;
    }
}
# 정확성  테스트
테스트 1 〉	통과 (0.02ms, 52.2MB)
테스트 2 〉	통과 (0.04ms, 53.2MB)
테스트 3 〉	통과 (0.03ms, 52.9MB)
테스트 4 〉	통과 (0.03ms, 51.9MB)
테스트 5 〉	통과 (0.02ms, 51.9MB)
테스트 6 〉	통과 (0.07ms, 52MB)
테스트 7 〉	통과 (0.02ms, 52.1MB)
테스트 8 〉	실패 (0.02ms, 53MB)
테스트 9 〉	실패 (0.02ms, 52.9MB)
테스트 10 〉	통과 (0.02ms, 52.7MB)
테스트 11 〉	통과 (0.03ms, 54.3MB)

# 효율성  테스트
테스트 1 〉	통과 (1.80ms, 55.9MB)
테스트 2 〉	통과 (1.35ms, 57.1MB)

으엥? 8,9번 테스트케이스에 걸린다.
반례를 생각해보자… 어떤 경우가 걸리는걸까?

반례는 생각외로 단순하다.
문자열의 길이 순으로 정렬된 배열이 아니기 때문에,
접두사가 될 수 있음에도 지나가는 경우가 생긴다.

먼저 정렬을 하고, 비교하는 방법은 어떨까?
정렬은 무조건 O(n)시간이 소요된다.
이미 O(n^2)이 돌고 있으므로, 추가적으로 루프를 돌리고 싶진 않다.
그럼 해결 방법이 무엇이 있을까?
비교 할 때 한쪽만 비교하는게 아니라 양측을 모두 비교하면 된다!


⭕ i <-> j 비교

class Solution {
    public boolean solution(String[] phone_book) {
        for(int i = 0; i < phone_book.length-1; i++){
            for(int j = i+1; j < phone_book.length; j++){
                if(phone_book[j].startsWith(phone_book[i])) return false;
                if(phone_book[i].startsWith(phone_book[j])) return false;
            }
        }
        return true;
    }
}
#정확성  테스트
테스트 1 〉	통과 (0.08ms, 52.8MB)
테스트 2 〉	통과 (0.02ms, 52.7MB)
테스트 3 〉	통과 (0.03ms, 52.9MB)
테스트 4 〉	통과 (0.02ms, 52.9MB)
테스트 5 〉	통과 (0.06ms, 52.1MB)
테스트 6 〉	통과 (0.02ms, 52.4MB)
테스트 7 〉	통과 (0.02ms, 52.6MB)
테스트 8 〉	통과 (0.02ms, 52.4MB)
테스트 9 〉	통과 (0.03ms, 53MB)
테스트 10 〉	통과 (0.02ms, 54.5MB)
테스트 11 〉	통과 (0.03ms, 52.1MB)

# 효율성  테스트
테스트 1 〉	통과 (0.05ms, 57.1MB)
테스트 2 〉	통과 (0.05ms, 57.5MB)

👏👏👏👏👏

댓글남기기