2026. 5. 4. 09:53ㆍProgrammers
문제 설명
영어 단어가 적힌 카드 뭉치 두 개로 원하는 단어 배열(goal)을 만들 수 있는지 판별하는 문제
- 카드 뭉치에서 카드를 순서대로 한 장씩 사용
- 한 번 쓴 카드는 다시 쓸 수 없음
- 카드를 건너뛰고 다음 카드로 넘어갈 수 없음
- 카드 뭉치의 단어 순서는 바꿀 수 없음
만들 수 있으면 "Yes", 못 만들면 "No" 반환
예시
cards1 = ["i", "drink", "water"]
cards2 = ["want", "to"]
goal = ["i", "want", "to", "drink", "water"]
cards1에서 "i"
cards2에서 "want", "to"
cards1에서 "drink", "water" 순서로 사용
>> "Yes"
문제 해석
처음엔 find로 카드가 있는지만 확인하면 된다고 생각했다
문제를 다시 보면 순서대로 한 장씩 이라는 조건이 있다
cards1에서 "water"를 쓰고 싶어도 앞에 있는 "i", "drink"를 먼저 다 써야 꺼낼 수 있다는 뜻
그러니까 단순히 카드가 있냐 없냐가 아니라 지금 맨 앞 카드가 goal과 맞는지 봐야 한다
각 카드 뭉치마다 "지금 어디까지 썼는지" 인덱스로 추적하면 깔끔하게 풀린다
문제 풀이
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
string solution(vector<string> cards1, vector<string> cards2, vector<string> goal) {
int idx1 = 0, idx2 = 0;
for(int i = 0; i < goal.size(); ++i)
{
if(idx1 < cards1.size() && cards1[idx1] == goal[i])
idx1++;
else if(idx2 < cards2.size() && cards2[idx2] == goal[i])
idx2++;
else
return "No";
}
return "Yes";
}
핵심 포인트
1. 인덱스로 "지금 맨 앞 카드" 추적하기
각 카드 뭉치는 순서대로만 꺼낼 수 있으니까, 지금 꺼낼 카드 위치를 인덱스로 들고 있으면 된다
int idx1 = 0, idx2 = 0;
idx1은 cards1에서 다음에 꺼낼 카드, idx2는 cards2에서 다음에 꺼낼 카드
goal을 하나씩 처리하면서 매칭된 쪽의 인덱스만 1씩 늘려주면 된다
2. 비교는 맨 앞만
cards1[idx1] == goal[i]
cards1 전체를 뒤지는 게 아니라 맨 앞 카드 하나하고만 비교한다
이렇게 해야 "순서대로 사용"이라는 조건을 자연스럽게 만족시킬 수 있다
3. 범위 체크
if(idx1 < cards1.size() && cards1[idx1] == goal[i])
처음엔 그냥 cards1[idx1] == goal[i]만 써볼까 했는데, 인덱스가 cards1 크기를 넘어가면 런타임 에러가 난다
C++의 &&는 앞 조건이 false면 뒤는 아예 평가 안 하는 단축 평가 방식이라
이 순서로 쓰면 인덱스가 범위를 벗어나도 cards1[idx1]에 접근하지 않는다
트러블슈팅
원인
처음에 find를 통해서 결과 카드에 들어가있는 카드면 true를 반환하면 된다고 생각해서 이렇게 작성했다.
for(int i = 0; i < goal.size(); ++i)
{
if(find(cards1.begin(), cards1.end(), goal[i]) != cards1.end())
continue;
else if(find(cards2.begin(), cards2.end(), goal[i]) != cards2.end())
continue;
else
return "No";
}
return "Yes";
언뜻 보면 맞는 것 같지만 테스트케이스 절반 정도가 실패했다
문제 파악
문제 조건을 다시 읽어보니 이런 문구가 있었다
원하는 카드 뭉치에서 카드를 순서대로 한 장씩 사용합니다
find는 그냥 "어딘가에 있는지"만 봐주는 함수다
순서를 전혀 신경쓰지 않으니까, 실제로는 못 꺼내는 카드인데도 통과시켜버린다
| cards1 | ["i", "drink", "water"] |
| cards2 | ["want", "to"] |
| goal | ["water", "i", ...] |
이 경우 goal[0] = "water"인데 cards1에는 분명 "water"가 있다
그래서 find는 통과시킨다
근데 실제로는 cards1은 "i" → "drink" → "water" 순서로만 꺼낼 수 있다
처음부터 "water"를 꺼내는 건 불가능
내 코드는 카드가 있다 = 사용 가능하다 라고 잘못 판단하고 있던 거였다
해결 방법
각 카드 뭉치마다 지금 어디까지 썼는지 인덱스로 추적하는 방식으로 바꿨다
int idx1 = 0, idx2 = 0;
if(idx1 < cards1.size() && cards1[idx1] == goal[i])
idx1++;
cards1[idx1]은 "지금 cards1에서 꺼낼 수 있는 맨 앞 카드" 다
이거랑 goal[i]를 비교하면 자연스럽게 "순서대로 사용" 조건이 지켜진다
순서가 중요한 문제에서는 인덱스를 이용하는 것이 좋다는 것을 알았다.
코드 흐름
예시를 직접 따라가보면 어떻게 동작하는지 한눈에 보인다
cards1 = ["i", "drink", "water"]
cards2 = ["want", "to"]
goal = ["i", "want", "to", "drink", "water"]
i goal[i]
cards1[idx1]
cards2[idx2]
결과 idx1 idx2
| 0 | "i" | "i" | - | cards1 사용 | 1 | 0 |
| 1 | "want" | "drink" | "want" | cards2 사용 | 1 | 1 |
| 2 | "to" | "drink" | "to" | cards2 사용 | 1 | 2 |
| 3 | "drink" | "drink" | (끝) | cards1 사용 | 2 | 2 |
| 4 | "water" | "water" | (끝) | cards1 사용 | 3 | 2 |
goal을 끝까지 다 매칭 >> "Yes"
'Programmers' 카테고리의 다른 글
| < 프로그래머스 C++ > 모의고사 (0) | 2026.05.07 |
|---|---|
| < 프로그래머스 C++ > 과일 장수 (0) | 2026.05.06 |
| < 프로그래머스 C++ > 2016년 (0) | 2026.05.01 |
| < 프로그래머스 C++ > 명예의 전당(1) (0) | 2026.04.30 |
| < 프로그래머스 C++ > 콜라 문제 (0) | 2026.04.29 |