문제 이름:
콜라 문제 ( Java )
문제 설명:
문제를 풀던 상빈이는 콜라 문제의 완벽한 해답을 찾았습니다.
상빈이가 푼 방법은 아래 그림과 같습니다. 우선 콜라 빈 병 20병을 가져가서 10병을 받습니다.
받은 10병을 모두 마신 뒤, 가져가서 5병을 받습니다.
5병 중 4병을 모두 마신 뒤 가져가서 2병을 받고, 또 2병을 모두 마신 뒤 가져가서 1병을 받습니다.
받은 1병과 5병을 받았을 때 남은 1병을 모두 마신 뒤 가져가면 1병을 또 받을 수 있습니다.
이 경우 상빈이는 총 10 + 5 + 2 + 1 + 1 = 19병의 콜라를 받을 수 있습니다.
처음 짠 코드 (문제 오답노트)
class Solution {
public int solution(int a, int b, int n) {
int answer = 0;
int temp = n;
int remain = 0;
while (temp > 0){
temp = n / a;
if(temp % a == 1){
remain++;
}
if(remain == 2){
temp = remain;
}
answer += n / a;
}
return answer;
}
}
저 문제에 대해 생각을 해보면 병 총 갯수에서 바꿔 줄 수 있는 병 갯수를 나눈 다음 그 결과를 더해주면 되는 거라고 생각했다 그리고 총 갯수가 홀수이면 남은 갯수를 따로 빼준 다음에 다시 나눠주고 더해주면 될 거라 생각해서
코드를 저렇게 짰다. 하지만 실행을 해보니 실행시간 초과라고 뜬다.
그래서 저 코드를 Chatgpt한테 물어봤다. 그 이유는 다음과 같다.
- 조건문 문제
temp는 n / a의 몫입니다. temp는 n을 a로 나눈 정수 결과이므로, temp % a를 계산하는 것은 의미가 없습니다. 예를 들어, n이 10이고 a가 3일 때, n / a는 3이 되고, temp % a는 3 % 3이 되어 결과는 0이 됩니다. 이 연산은 의미가 없으며, temp % a를 1과 비교하는 조건문은 항상 false가 됩니다.
이 문제가 잘 이해 되지 않아 다시 질문을 했다.
11 / 2 = 5이고 5 % 2 = 1 일경우 1번 조건문에 성립돼서 true가 되지만 이 로직 전체에서는 의미가 없다는 것이다.
temp가 n / a의 몫이라면, temp % a == 1이 성립할 때 remain을 증가시키는 이유가 불명확합니다. - 조건문 문제2
이 부분의 로직도 불명확합니다. remain은 temp % a == 1 조건을 만족할 때마다 증가하는 값입니다. 그러나 remain이 2가 되면 temp에 remain을 저장하는 것은 논리적으로 문제가 있습니다. temp는 반복문에서 계속해서 n / a의 값을 가져야 하는데, remain이 2일 때 temp에 2를 할당하는 것은 의미가 없습니다. 이 부분의 의도를 정확히 이해하기 어렵습니다
이것또한 다시 질문을 해봤다.
그랬더니 논리적 일관성 부족이라는 문제가 있다고 했다.
remain이 2가 되면 temp에 remain을 할당하는 것은 의미가 없습니다. 왜냐하면 temp는 n / a의 결과로 정의되며,
이를 임의의 값(remain)으로 덮어쓰는 것은 논리적 일관성이 없기 때문입니다.
temp를 remain으로 설정해도 루프에서 다시 temp = n / a로 덮어쓰기 때문에, 실제로는 아무 의미가 없습니다. - answer에 고정된 값 정의
answer에 n / a를 계속 더해준다고 나와있는데 n을 바꿔주는거 없이 고정된 값을 나누고 더해주기 때문에
처음 갯수인 20 / 2인 10이 계속 더해진다 - 반목문 문제
저 while문에서 temp가 0보다 높을 때 반복문을 실행한다고 나와있는데 while문 내부에서 temp를 새로
정의해 준게 없어서 무한루프에 빠진다
문제 풀이
class Solution {
public int solution(int a, int b, int n) {
int answer = 0;
while (n >= a) { // n이 a보다 크거나 같을 동안 반복
int exchange = n / a; // 교환할 수 있는 병의 수
int remain = n % a; // 교환 후 남는 병의 수
answer += exchange * b; // 교환 후 얻은 새로운 병의 수를 누적
n = remain + exchange * b; // 새로운 n은 남은 병과 얻은 병의 합
}
return answer;
}
}
저 코드를 보면
while문 조건인 n >= a 는 병을 바꿀 수 있는 최소가 a이기 때문에 a미만이면 반복문을 종료한다.
exchange에 n / a을 정의한다 (n이 20이고 a가 2면 20 / 2 = 10)
remain에는 n % a을 정의한다 (20 % 2 = 0)
answer에는 exchange의 값에 b를 곱한 값을 더한다. (b는 1이다) (10 * 1 = 10)
n에는 remain의 값에 exchange와 b를 곱한 값을 더한다 (0 + 10 * 1 = 10)
이 과정을 반복한다.
'프로그래머스 문제' 카테고리의 다른 글
[프로그래머스] (Java) 2016년 (0) | 2024.07.19 |
---|---|
프로그래머스 Java (푸드 파이트 대회) (0) | 2024.07.18 |
프로그래머스 JAVA( 명예의 전당 (1) ) (0) | 2024.07.18 |
프로그래머스 SQL 문제(재구매가 일어난 상품과 회원리스트) (0) | 2024.07.18 |
프로그래머스 SQL 과일로 만든 아이스크림 (0) | 2024.07.17 |