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;
    }
}