-
[Algorithm: 해시] 프로그래머스 <의상>Algorithms 2026. 5. 18. 15:32Hash 조합론 Java Programmers Lv.2
문제
https://school.programmers.co.kr/learn/courses/30/lessons/42578?language=java
프로그래머스
SW개발자를 위한 평가, 교육의 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프
programmers.co.kr
문제 설명
의상의 종류별로 최대 1개씩 착용할 수 있고, 최소 1개는 입어야 한다. 가능한 서로 다른 의상 조합의 수를 구하는 문제다.
clothes return [["yellow_hat","headgear"],["blue_sunglasses","eyewear"],["green_turban","headgear"]] 5 [["crow_mask","face"],["blue_sunglasses","face"],["smoky_makeup","face"]] 3
핵심 아이디어: 곱의 법칙
처음엔 모든 조합을 직접 나열하려 할 수 있다. 하지만 의상 종류가 늘어날수록 경우의 수가 폭발적으로 증가한다. 수학적으로 접근하면 훨씬 단순하다.
각 종류에서 "안 입는" 선택지를 하나 추가하면,
종류별 선택지 수는 (해당 종류 의상 수 + 1)이 된다.
전체 경우의 수 = 각 종류별 선택지를 모두 곱한 값
여기서 모든 종류를 다 안 입는 경우 1가지를 빼면 정답이다.예시 1 — headgear 2개, eyewear 1개
headgear 2개 + 안입기×eyewear 1개 + 안입기=(2+1) 3가지×(1+1) 2가지=6 전체−1 아무것도 안입기=5 정답왜 (n+1)을 곱하는가?
각 종류에서 고를 수 있는 선택지를 표로 정리해보자.
headgear(2개) × eyewear(1개) 전체 조합표
headgear \\ eyewear안입기blue_sun
glasses소계안입기둘 다 없음blue_sun1yellow_hatyellow_hatyellow+blue2green_turbangreen_turbangreen+blue2소계336-1=5빨간 칸(둘 다 안입기)은 "최소 1개" 조건 위배 → 마지막에 -1로 제거
안입기를 선택지에 포함하는 이유:
"headgear를 안 입고 eyewear만 입는 경우"처럼 특정 종류를 생략하는 선택도 유효한 조합이다.
"안입기"를 각 종류에 1개 추가해야 이런 경우를 자연스럽게 계산할 수 있다.HashMap으로 종류별 개수 세기
의상 배열을 순회하면서 종류(key)별 개수(value)를 HashMap에 저장한다.
예시 1 HashMap 구성 과정
headgear → 2 (yellow_hat, green_turban)eyewear → 1 (blue_sunglasses)예시 2 HashMap 구성 과정
face → 3 (crow_mask, blue_sunglasses, smoky_makeup)종류가 하나뿐이므로: (3+1) - 1 = 3
for (int i = 0; i < clothes.length; i++) { if (!map.containsKey(clothes[i][1])) { map.put(clothes[i][1], 1); // 처음 등장한 종류 } else { int cnt = map.get(clothes[i][1]); map.put(clothes[i][1], cnt + 1); // 이미 있는 종류 카운트 증가 } }Java의
getOrDefault()를 활용하면 더 간결하게 작성할 수 있다.map.put(clothes[i][1], map.getOrDefault(clothes[i][1], 0) + 1);전체 풀이 흐름
1clothes 배열을 순회해 종류별 의상 개수를 HashMap에 저장2answer = 1로 초기화 후, 각 종류의(value + 1)을 차례로 곱하기3마지막에answer - 1반환 (아무것도 안 입는 경우 제거)
최종 코드
import java.util.*; class Solution { public int solution(String[][] clothes) { int answer = 1; HashMap<String, Integer> map = new HashMap<>(); // 종류별 의상 개수 카운트 for (int i = 0; i < clothes.length; i++) { if (!map.containsKey(clothes[i][1])) { map.put(clothes[i][1], 1); } else { int cnt = map.get(clothes[i][1]); map.put(clothes[i][1], cnt + 1); } } // 각 종류별 (개수 + 1) 곱하기 → +1은 "안입기" 선택지 for (int value : map.values()) { answer *= (value + 1); } // 모든 종류를 안 입는 경우 제거 return answer - 1; } }
정리
HashMap 집계clothes[i][1](종류)을 key로, 개수를 value로 저장. O(n)으로 종류별 집계 완료.(n+1) 곱셈각 종류에 "안입기" 선택지 1개를 추가. 종류별 독립 선택이므로 곱의 법칙 적용.answer = 1로 초기화곱셈 누적이므로 0이 아닌 1로 시작. 0으로 시작하면 모든 값이 0이 된다.마지막 -1"모든 종류를 다 안 입는" 경우 1가지는 최소 1개 조건 위배. 곱셈 결과에서 제거.이 문제의 핵심은 완전탐색 없이 수학적으로 경우의 수를 구하는 것이다.
"안입기"를 선택지에 포함해 곱의 법칙을 적용하고, 마지막에 -1로 조건을 충족하는 패턴은
조합 문제에서 반복적으로 등장하는 중요한 기법이다.* 이 포스팅은 Claude AI의 도움을 받아서 작성되었습니다.
'Algorithms' 카테고리의 다른 글
[Algorithm: 그래프] 프로그래머스 <순위> (0) 2026.06.04 [Algorithm: 큐] 프로그래머스 <다리를 지나는 트럭> (0) 2026.05.17 [Algorithm: 큐] 프로그래머스 <프로세스> (0) 2026.05.17 [Algorithm: DFS] 프로그래머스 <퍼즐 조각 채우기> (0) 2026.05.13 [Algorithm: DFS] 프로그래머스 <단어 변환> (0) 2026.05.02