본문 바로가기

취미/코딩테스트

프로그래머스 [전화번호 목록 - Hash]

문제 설명
전화번호부에 적힌 전화번호 중, 한 번호가 다른 번호의 접두어인 경우가 있는지 확인하려 합니다.
전화번호가 다음과 같을 경우, 구조대 전화번호는 영석이의 전화번호의 접두사입니다.

  • 구조대 : 119
  • 박준영 : 97 674 223
  • 지영석 : 11 9552 4421
전화번호부에 적힌 전화번호를 담은 배열 phone_book 이 solution 함수의 매개변수로 주어질 때, 어떤 번호가 다른 번호의 접두어인 경우가 있으면 false를 그렇지 않으면 true를 return 하도록 solution 함수를 작성해주세요.
제한 사항
  • phone_book의 길이는 1 이상 1,000,000 이하입니다.
    • 각 전화번호의 길이는 1 이상 20 이하입니다.
    • 같은 전화번호가 중복해서 들어있지 않습니다.
입출력 예제


입출력 예 설명
입출력 예 #1
  앞에서 설명한 예와 같습니다.

입출력 예 #2
  한 번호가 다른 번호의 접두사인 경우가 없으므로, 답은 true입니다.

입출력 예 #3
  첫 번째 전화번호, “12”가 두 번째 전화번호 “123”의 접두사입니다. 따라서 답은 false입니다.

 

코드(선형탐색1)

  딱 떠오르는데로 적고 테스트 통과라 기분 좋았으나, 효율성에서 막혔다. ^^

#include <string>
#include <vector>
#include <algorithm>

using namespace std;

bool solution(vector<string> phone_book) {
    if(phone_book.size() < 2) return true;
    
    sort(phone_book.begin(), phone_book.end(), [](string a, string b){
        return a.size()<b.size();
    });
        
    for(int i=0; i< phone_book.size()-1; i++){
        for(int j=i+1; j < phone_book.size(); j++){
            string a = phone_book[i];
            string b = phone_book[j];
            string c = b.substr(0,a.size());            
            if(a == c) return false;
        }
    }
    return true;
}

 

코드(선형탐색2 - 주관적으로 가장 맘에드는 정답)

  string의 find 함수를 활용. 때문에 정렬 방식도 바꾸었다. 번호길이 -> 기본정렬(닮은순서+길이).

  만약 번호 길이순 정렬의 경우, for문이 한 번 더 필요하다.

  string find 함수는 vector find 함수와 달리 찾은 횟수를 반환한다.

#include <string>
#include <vector>
#include <algorithm>

using namespace std;

bool solution(vector<string> phone_book) {
    if(phone_book.size() < 2) return true;
    sort(phone_book.begin(), phone_book.end());
    
    for(int i=1; i<phone_book.size(); ++i){
        if(phone_book[i].find(phone_book[i-1])==0) return false;
    }
    
    return true;
}

 

코드(해시 - 해당 문제의 알고리즘에 맞는 방법)

  해시 탭에 있으니 요렇게도.. 사실 해시맵 사용이 잘 기억 안 났다.

  벡터에 담고 풀어도 아래와 같은 O(N log N) 형식을 띄게 된다.

#include <string>
#include <vector>
#include <unordered_map> // hash_map

using namespace std;

bool solution(vector<string> phone_book) {
    if(phone_book.size() < 2) return true;
    
    unordered_map<string,int> book;
    for(string num : phone_book) book[num] = 1;
    
    for(int i=0; i<phone_book.size(); i++){
        string tempNum;
        for(int j=0; j<phone_book.size(); j++){
            tempNum += phone_book[i][j];
            if(book[tempNum] && tempNum != phone_book[i]) return false;
        }
    }
    
    return true;
}