카드뭉치

나의 기록·2026년 8월 13일

코딩테스트

목록 보기
33/35

문제

프로그래머스 - 카드 뭉치 (Lv.1)

cards1, cards2 두 뭉치에서 순서를 바꾸지 않고 앞에서부터만 카드를 꺼내서 goal 배열을 만들 수 있는지 판단하는 문제임

처음에 헷갈렸던 부분 - "번갈아 뽑아야 하나?"

처음엔 배열이 두 개니까 하나 뽑으면 다음엔 다른 배열에서 뽑아야 한다고 생각함. 근데 예시를 손으로 직접 따라가보니

cards1 = ["i", "drink", "water"]
cards2 = ["want", "to"]
goal   = ["i", "want", "to", "drink", "water"]

여기서 "want"랑 "to"는 연속으로 cards2에서 나오고, "drink"랑 "water"도 연속으로 cards1에서 나옴. 즉 번갈아 뽑는 게 아니라는 걸 깨달음.

결론적으로 cards1용 포인터 i, cards2용 포인터 j를 각각 독립적으로 두고, 그 배열에서 카드를 쓸 때만 해당 포인터를 올리는 방식으로 접근해야 함.

goal 인덱스를 따로 안 둬도 되는 이유

매 반복마다 i 아니면 j 둘 중 딱 하나만 1씩 올라감. 그럼 지금까지 사용한 카드 개수는 항상 i + j랑 같음. 그래서 goal에서 지금 확인해야 할 위치도 i + j로 표현 가능함 → 별도로 k 인덱스를 만들 필요가 없었음.

시행착오 1 - 비교 대상을 잘못 씀

처음 코드에서 goal[k].equals(goal[i])처럼 cards1[i]가 아니라 goal[i]랑 비교하는 실수를 함. 당연히 cards1[i]로 고쳐야 했음.

시행착오 2 - ==로 문자열 비교

자바에서 String을 ==로 비교하면 값이 아니라 주소(참조)를 비교하는 거라 위험함. .equals()로 값 비교하도록 고침.

시행착오 3 - 범위 체크 없이 배열 재접근

실패 조건("둘 다 매칭 안 됨")을 확인하려고

if(!goal[k].equals(cards1[i]) & !goal[k].equals(cards2[j])){ ... }

이런 식으로 cards1[i], cards2[j]를 범위 체크 없이 또 조회하는 코드를 짬. i나 j가 이미 배열 길이만큼 다 써버린 상태에서 이 인덱스로 접근하면 ArrayIndexOutOfBoundsException이 터질 수 있는 상황이었음.

→ "범위 안에 있다" + "값이 같다"를 하나의 조건(&&)으로 묶어서, 그 결과 자체를 "이 배열이 후보가 될 수 있는지"로 쓰도록 구조를 바꿈. 이렇게 하면 범위를 벗어난 배열은 자동으로 후보 탈락 처리되니까 별도로 다시 배열에 접근할 필요가 없어짐.

시행착오 4 - if, if를 따로 써서 생긴 동시 매칭 문제

후보 조건 두 개를 if if로 각각 따로 쓰면, 우연히 cards1[i]랑 cards2[j]가 둘 다 goal이랑 같을 때 i, j가 동시에 올라가버릴 수 있음. goal은 한 칸만 채웠는데 카드는 두 장을 써버리는 셈이라 순서가 꼬임.

if - else if 구조로 바꿔서 두 후보 중 최대 하나만 선택되게 고침.

시행착오 5 - 불필요한 변수/분기 정리

처음엔 candidate라는 boolean이랑 answer라는 String 변수를 두고, 실패하면 break로 while문만 빠져나온 뒤 answer를 return하는 구조였음.

break는 반복문만 종료시키고 값을 돌려주는 기능이 없어서, 실패 여부를 기억해둘 변수(answer, candidate)가 따로 필요했던 거였음. 만약 그 상태에서 break 대신 아무 변수도 없이 그냥 break만 쓰면, 반복문을 빠져나온 뒤 이어지는 코드(return "Yes")로 흘러가버려서 실패 케이스도 "Yes"로 반환되는 버그가 생길 뻔했음.

→ 실패가 확정되는 그 자리에서 바로 return "No"로 메서드를 통째로 끝내버리면, 종료와 값 반환이 동시에 처리되니까 candidate, answer 변수도 break도 전부 필요 없어짐. while문을 정상적으로 다 빠져나왔다는 것 자체가 "다 맞았다"는 뜻이라 그 뒤에 return "Yes" 한 줄이면 끝남.

최종 코드

class Solution {
    public String solution(String[] cards1, String[] cards2, String[] goal) {
        int i = 0;
        int j = 0;

        while (goal.length > i + j) {
            if (cards1.length > i && goal[i + j].equals(cards1[i])) {
                i++;
            } else if (cards2.length > j && goal[i + j].equals(cards2[j])) {
                j++;
            } else {
                return "No";
            }
        }

        return "Yes";
    }
}

배운 점

  • 규칙을 지레짐작하지 말고 주어진 예시로 직접 손트레이싱해서 검증해야 함
  • 배열 인덱스로 접근하기 전엔 항상 범위 체크를 먼저 하고, &&로 묶어서 짧은회로(short-circuit) 평가를 활용해야 안전함
  • 자바에서 문자열 값 비교는 무조건 .equals(), ==는 참조 비교라 다름
  • break는 반복문만 종료시키고 값을 못 돌려줌 / return은 메서드 자체를 종료시키면서 값도 같이 반환함 → 상황에 맞게 골라 써야 함
profile
뭐든 남겨본다

0개의 댓글