2026. 4. 27. 10:23ㆍProgrammers

문자열 s가 주어졌을 때, s의 각 위치마다 자신보다 앞에 나왔으면서 자신과 가장 가까운 곳에 있는 같은 글자가 어디 있는지 알아내는 문제이다.
s = "banana" result = [-1, -1, -1, 2, 2, 2]
s = "foobar" result = [-1, -1, 1, -1, -1, -1]
문제 해석
각 글자에서 다음 두 가지를 확인하면 된다.
- 자신 이전 구간에 같은 글자가 있는가?
- 있다면 가까운 위치까지의 거리는?
여기서 핵심은 "가장 가까운" 이라는 조건이다. 앞에 글자가 있어도 자기 자신과 제일 가까운 것 하나만 찾으면 된다.
이를 구하기 위해서 역순 탐색 기법을 사용했다.
문제 풀이
#include <string>
#include <vector>
using namespace std;
vector<int> solution(string s) {
vector<int> answer;
for (int i = 0; i < s.size(); i++) {
if (i == 0) {
answer.push_back(-1);
continue;
}
size_t pos = s.rfind(s[i], i - 1);
if (pos == string::npos) {
answer.push_back(-1);
} else {
answer.push_back(i - pos);
}
}
return answer;
}
핵심 포인트
1. rfind()
rfind는 문자열을 뒤에서부터 검색해서 일치하는 위치를 반환하는 함수이다.
문자열.rfind(찾을문자, 시작위치);
- 찾을 문자 - 검색할 문자(또는 부분 문자열)
- 시작 위치 - 검색을 시작할 인덱스 값. 여기서부터 앞쪽으로 검색을 이어나간다.
이번 문제에서는 s.rfind(s[i], i - 1) 처럼 사용했다.
"i번째 글자와 같은 문자를 i-1 위치부터 앞쪽으로 검색"
이라는 뜻이다.
2. string::npos
rfind나 find함수는 결과를 찾지 못했을 때, string::npos라는 값을 반환한다.
size_t pos = s.rfind(s[i], i - 1);
if (pos == string::npos) {
// 찾지 못한 경우
}
다른 함수의 종류와는 좀 다르게 string의 find는 이러한 값을 내보낸다.
| 함수 종류 | 못 찾을 때 반환값 |
| Vector의 find | end() |
| String의 find | string::npos |
| map의 find | end() |
3. 거리 계산
answer.push_back(i - pos);
가장 가까운 같은 글자의 위치를 찾았다면, 현재 위치 i에서 그 위치 pos값을 빼면 거리가 나온다.
banana의 마지막 a를 예로 들면
s.rfind('a', 4) > 4번 인덱스부터 거꾸로 검색 > 인덱스 3에서 a 발견
5 - 3 = 2
4. 첫 글자 예외 처리
첫 글자는 비교할 글자가 없으므로 바로 -1을 입력해주면 된다.
입력이 완료된 후에 continue로 다음 반복문을 진행해주는 것도 잊지 않는다.
if (i == 0) {
answer.push_back(-1);
continue;
}
다른 풀이 - map활용(코드리뷰)
#include <string>
#include <vector>
#include <map>
using namespace std;
vector<int> solution(string s)
{
map<char, int> mp;
vector<int> answer;
for (int i = 0; i < s.size(); ++i)
{
if (mp.find(s[i]) != mp.end()) answer.push_back(i - mp[s[i]]);
else answer.push_back(-1);
mp[s[i]] = i;
}
return answer;
}
rfind는 매번 앞쪽 전체를 검색하기 때문에 시간 복잡도가 O(N^2)에 가깝다. N이 10000정도는 큰 문제는 없지만, 더 효율적인 방법으로 마지막 등장 위치를 기록하는 방식이 있다.
동작 원리
- mp[c]에 문제 c가 마지막에 등장한 위치를 저장
- 새 글자를 만나면 맵에서 즉시 조회
- 처리 후 자신의 위치로 갱신
이 방식의 장점은 이전 위치를 다시 검색할 필요가 없다는 것이다. rfind처럼 매번 앞쪾을 거꾸로 훑지 않고, 맵에서 한 번에 꺼낸다.
map의 find패턴
if (mp.find(s[i]) != mp.end())
맵에 키가 있다면 거리를 계산하는 조건문이다.
이렇게
이전에 본 무언가의 위치를 기억해야 할 때
는 맵 계열 자료구조를 떠올리면 좋다.
'Programmers' 카테고리의 다른 글
| < 프로그래머스 C++ > 콜라 문제 (0) | 2026.04.29 |
|---|---|
| < 프로그래머스 C++ > 푸드 파이트 대회 (0) | 2026.04.28 |
| < 프로그래머스 C++ > 두 개 뽑아서 더하기 (0) | 2026.04.24 |
| < 프로그래머스 C++ > K번째 수 (0) | 2026.04.23 |
| < 프로그래머스 C++ > 문자열 내 마음대로 정렬하기 (0) | 2026.04.22 |