Algorithm/Java
[프로그래머스/JAVA] 할인행사
dbfl9911
2025. 1. 22. 11:34
https://school.programmers.co.kr/learn/courses/30/lessons/131127
프로그래머스
SW개발자를 위한 평가, 교육, 채용까지 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프
programmers.co.kr
📌 문제 요약
정현이가 원하는 제품과 수량이 10일간의 할인 목록과 일치하는 구간을 찾아 회원 가입 날짜를 계산해야 합니다. 기존 코드에서 결과가 정확하지 않은 이유를 분석하고 수정 내용을 정리합니다.
[ 오답 노트 ]
❌ 기존 오답 코드
import java.util.*;
class Solution {
public int solution(String[] want, int[] number, String[] discount) {
int answer = 0;
// 10일 동안 할인 진행
// 원하는 제품은 바나나 3개, 사과 2개, 쌀 2개, 돼지고기 2개, 냄비 1개
// (총 14일 동안이므로 14-10+1=총 5일간 확인하기)
// (1DAY)치킨, 사과, 사과, 바나나, 쌀, 사과, 돼지고기, 바나나, 돼지고기, 쌀 -> 냄비 없으므로 X
// 치킨1개, 사과3개, 바나나2개, 쌀2개, 돼지고기2개 형태로
// (2DAY)사과, 사과, 바나나, 쌀, 사과, 돼지고기, 바나나, 돼지고기, 쌀, 냄비 -> 바나나 없으므로 X
// 사과3개, 바나나2개, 쌀2개, 돼지고기2개, 냄비1개 형태로
// (3DAY)사과, 바나나, 쌀, 사과, 돼지고기, 바나나, 돼지고기, 쌀, 냄비, 바나나 -> 조건 충족 O
// 사과2개, 바나나3개, 쌀2개, 돼지고기2개, 냄비1개 형태로
// (4DAY)바나나, 쌀, 사과, 돼지고기, 바나나, 돼지고기, 쌀, 냄비, 바나나, 사과 -> 조건 충족 O
// 바나나3개, 쌀2개, 사과2개, 돼지고기2개, 냄비1개 형태로
// (5DAY)쌀, 사과, 돼지고기, 바나나, 돼지고기, 쌀, 냄비, 바나나, 사과, 바나나 -> 조건 충족 O
// 쌀2개, 사과2개, 돼지고기2개, 바나나3개, 쌀2개, 냄비1개 형태로
// want와 number배열 해시맵으로 바꾸기
// ex) 바나나 3개, 사과 2개, 쌀 2개, 돼지고기 2개, 냄비 1개
HashMap<String, Integer> hm1 = new HashMap<>();
for(int z = 0; z < want.length; z++) {
hm1.put(want[z], number[z]);
}
for(int i = 0; i < discount.length - 10 + 1; i++) { // 1day~5day
HashMap<String, Integer> hm2 = new HashMap<>();
// 1. 처음나오는 요소이면 1로 초기화, 기존에 있던 요소이면 값 증가
// ex) (1DAY)치킨 1개, 사과3개, 바나나 2개, 쌀 2개, 돼지고기2개 형태로
hm2.put(discount[i], hm2.getOrDefault(discount[i],0)+1);
// 2. hm1과 hm2 해시맵 비교해서 일치하면 answer+1
for(int t = 0; t < want.length; t++) {
// hm1의 키 == hm2 키
if(hm2.containsKey(want[t])) {
// 그 키의 값까지 같다면
if(hm2.get(want[t]) >= hm1.get(want[t])){
answer++;
}
}
}
}
return answer;
}
}
📌 기존 코드의 문제점 및 해결 방안
1. hm2에 10일간의 할인 정보를 누적하는 부분 오류
기존 코드인 hm2.put(discount[i], hm2.getOrDefault(discount[i],0)+1); 의 아래처럼 반복문을 추가해야 한다.
기존 코드는 상단 반복문인 DAY에 맞춰서 반복문을 돌리게 되어있어 10일간의 할인 정보를 누적할 수 없다.
for (int j = i; j < i + 10; j++) {
hm2.put(discount[j], hm2.getOrDefault(discount[j], 0) + 1);
}
2. hm1과 hm2를 비교할 때 조건 충족 오류
기존 코드는 부정확한 로직으로
- 아래와 같이 조건을 모두 만족하는지 여부를 저장하는 플래그 변수를 추가하고,
- for (String key : hm1.keySet())의 반복문을 사용해 모든 hm1의 키(제품 이름)를 순회하면서 조건을 확인해야 한다.
- hm2의 값이 hm1의 값보다 작다면 조건 충족을 못하므로 false를 반환, 그외는 true를 반환하도록 하여 정답 도출
// 조건 비교: 원하는 제품 수량과 일치하는지 확인
boolean isMatched = true;
for (String key : hm1.keySet()) {
if (hm2.getOrDefault(key, 0) < hm1.get(key)) {
isMatched = false;
break;
}
}
if (isMatched) {
answer++;
}
[ 정답 코드 & 올바른 풀이 ]
📌 정답 코드
import java.util.*;
class Solution {
public int solution(String[] want, int[] number, String[] discount) {
int answer = 0;
// want와 number배열 해시맵으로 바꾸기
// ex) 바나나 3개, 사과 2개, 쌀 2개, 돼지고기 2개, 냄비 1개
HashMap<String, Integer> hm1 = new HashMap<>();
for(int z = 0; z < want.length; z++) {
hm1.put(want[z], number[z]);
}
for(int i = 0; i < discount.length - 10 + 1; i++) { // 1day~5day
HashMap<String, Integer> hm2 = new HashMap<>();
// 1. 처음나오는 요소이면 1로 초기화, 기존에 있던 요소이면 값 증가
// ex) (1DAY)치킨 1개, 사과3개, 바나나 2개, 쌀 2개, 돼지고기2개 형태로
for (int j = i; j < i + 10; j++) {
hm2.put(discount[j], hm2.getOrDefault(discount[j],0)+1);
}
// 2. hm1과 hm2 해시맵 비교해서 일치하면 answer+1
boolean isMatched = true;
for (String key : hm1.keySet()) {
if (hm2.getOrDefault(key, 0) < hm1.get(key)) {
isMatched = false;
break;
}
}
if (isMatched) {
answer++;
}
}
return answer;
}
}