Programmers 42577 전화번호 목록 (Hash & Sorting)
Programmers 42577 전화번호 목록 (Hash & Sorting)
문제
전화번호 목록 링크 전화번호부에 적힌 전화번호 중, 한 번호가 다른 번호의 접두어인 경우가 있는지 확인하는 문제입니다.
- $N$ (전화번호 개수): 최대 1,000,000
- $L$ (전화번호 길이): 최대 20
문자열 문제인데 cpp로 해보는게 좋을것 같았음. 방법이 여러가지다.
복잡도 분석
1. Hash 방식
- Time Complexity: $O(N \cdot L^2)$
- $N$개의 번호를 삽입($O(N \cdot L)$)하고, 각 번호마다 $L$개의 접두어를 생성하여 해시 셋에서 탐색($O(L)$)합니다.
- Space Complexity: $O(N \cdot L)$
- 모든 문자열을
unordered_set에 저장합니다.
- 모든 문자열을
2. Sorting 방식
- Time Complexity: $O(L \cdot N \log N)$
- 정렬에 $O(L \cdot N \log N)$이 소요되며, 이후 인접 원소 비교에 $O(N \cdot L)$이 소요됩니다.
- Space Complexity: $O(L)$
- 정렬 시 발생하는 오버헤드 외에 추가 자료구조를 거의 사용하지 않습니다.
접근법
전략 1: 해시를 이용한 부분 문자열 탐색
모든 단어를 해시에 넣고, 각 단어의 모든 접두어가 해시에 있는지 묻는 방식입니다.
전략 2: 정렬을 이용한 인접 원소 비교
사전순으로 정렬하면 접두어 관계인 단어들은 반드시 붙어있게 된다는 성질을 이용합니다.
graph TD
A[문제 해결 전략] --> B[해시 기반]
A --> C[정렬 기반]
B --> B1[전체 단어 Hash Set 삽입]
B1 --> B2[각 단어의 Prefix 생성 후 Set 존재 확인]
C --> C1[사전순 정렬]
C1 --> C2[i번째와 i+1번째의 접두어 관계 확인]
풀이
[풀이 1] Hash 기반
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <string>
#include <vector>
#include <unordered_set>
using namespace std;
bool solution(vector<string> phone_book) {
bool answer = true;
unordered_set<string> s(phone_book.begin(), phone_book.end());
for(const auto& e : phone_book){
for(int i = 1; i < e.size(); i++){
if (s.find(e.substr(0, i)) != s.end())
return false;
}
}
return answer;
}
[풀이 2] Sorting 기반
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
bool solution(vector<string> phone_book) {
bool answer = true;
sort(phone_book.begin(), phone_book.end());
for(int i = 0; i < phone_book.size() - 1; i++){
// 앞의 번호가 뒤 번호의 접두어인지 확인
if(phone_book[i] == phone_book[i+1].substr(0, phone_book[i].size()))
return false;
}
return answer;
}
Code Review
1. Hash vs Sorting
- 데이터 크기 관점: $N=10^6$일 때, $N \log N$은 약 $2 \times 10^7$입니다. $L^2$은 $400$입니다. 두 방식 모두 시간 내에 충분히 들어오지만, Sorting 방식이 메모리 사용량 측면에서 훨씬 경제적입니다.
- 최적화: Sorting 풀이에서
substr()대신compare()또는 C++20의starts_with()를 사용하면 불필요한 문자열 복사를 막아 성능을 극대화할 수 있습니다.
trie
trie로 풀어보려고 공부중
This post is licensed under CC BY 4.0 by the author.