출처: 2020 KAKAO Blind Recruitment
문제 링크: programmers.co.kr/learn/courses/30/lessons/60060
코딩테스트 연습 - 가사 검색
programmers.co.kr
문제에 대한 자세한 내용은 링크를 통해 직접 확인하시기 바랍니다.
이분 탐색 문제를 풀던 중 나온, 카카오 기출문제들이 으레 그렇듯 꽤 난이도 있는 문제입니다.
정확히는 정석대로 이분 탐색을 구현하는 것이 아닌, lower_bound와 upper_bound 함수를 이용하여 구현하는 방식입니다.
문제를 접근한 순서는 다음과 같습니다.
- 각 단어를 길이에 따라 나눈다.
- 각 단어 길이 배열을 알파벳 순서로 정렬한다.
- 이진 탐색을 통해 쿼리의 단어로 시작하는 마지막 단어와 첫 단어의 인덱스를 구하고, 그 차이를 구합니다. (?를 a와 z로 대체한 후, 그 사이 구간의 갯수를 구하면 편합니다.)
- 접두사가 ?로 시작하는 쿼리의 경우, 계산을 위해 reverse를 이용하여 문자열을 뒤집은 후 2~3의 과정을 수행한다.
- 각 결과를 정답 배열에 저장한다.
별도로 두 개의 함수를 작성하였습니다.
countByRange 함수는 주어진 정렬된 문자열 배열 내에서, 시작점과 끝점 사이의 갯수를 구하는 함수입니다.
lower_bound와 upper_bound 함수를 사용했고, 예를 들어 찾고자 하는 단어가 'fro??' 라면, froaa ~ frozz 사이의 단어의 수를 구합니다.
replaceAll 함수는 문자열 내의 특정 문자를 다른 문자로 바꿔주는 함수입니다. ?를 a 또는 z로 바꾸는 역할을 합니다.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <string> | |
#include <vector> | |
#include <algorithm> | |
using namespace std; | |
#define MAX_N 10001 | |
int countByRange(vector<string> &v, string leftValue, string rightValue) { | |
vector<string>::iterator rightIndex = upper_bound(v.begin(), v.end(), rightValue); | |
vector<string>::iterator leftIndex = lower_bound(v.begin(), v.end(), leftValue); | |
return rightIndex - leftIndex; | |
} | |
string replaceAll(string str, string from, string to) { | |
string result = str; | |
int pos = 0; | |
while ((pos = result.find(from, pos)) != string::npos) { | |
result.replace(pos, from.size(), to); | |
pos += to.size(); | |
} | |
return result; | |
} | |
vector<string> arr[MAX_N]; | |
vector<string> reversed_arr[MAX_N]; | |
vector<int> solution(vector<string> words, vector<string> queries) { | |
vector<int> answer; | |
for (int i = 0; i < words.size(); i++) { | |
string word = words[i]; | |
arr[word.size()].push_back(word); | |
reverse(word.begin(), word.end()); | |
reversed_arr[word.size()].push_back(word); | |
} | |
for (int i = 0; i < MAX_N; i++) { | |
sort(arr[i].begin(), arr[i].end()); | |
sort(reversed_arr[i].begin(), reversed_arr[i].end()); | |
} | |
for (int i = 0; i < queries.size(); i++) { | |
string q = queries[i]; | |
int result = 0; | |
if (q[0] != '?') | |
result = countByRange(arr[q.size()], replaceAll(q, "?", "a"), replaceAll(q, "?", "z")); | |
else { | |
reverse(q.begin(), q.end()); | |
result = countByRange(reversed_arr[q.size()], replaceAll(q, "?", "a"), replaceAll(q, "?", "z")); | |
} | |
answer.push_back(result); | |
} | |
return answer; | |
} |
'알고리즘, 문제해결 > 알고리즘 문제풀이' 카테고리의 다른 글
[백준 12100번] 2048 (easy) (0) | 2021.03.24 |
---|---|
[백준 15401번] 퇴사 (0) | 2021.03.11 |
[백준 2110번] 공유기 설치 (2) | 2021.03.08 |
[프로그래머스] 실패율 (0) | 2021.03.01 |
[백준 1647번] 도시 분할 계획 (0) | 2021.02.13 |
댓글