- 문제설명
- 제한사항
- 예시 & 입출력 예
- 해결과정
- 첫번째 입출력 예시인 16을 보면
1) 1층 내려가는 버튼을 6번 누른 뒤 10층 내려가는 버튼을 한번 눌러 총 7번의 버튼으로 0층까지 내려올 수 있고
2) 1층 올라가는 버튼을 4번 누른 뒤 10층 내려가는 버튼을 두번 눌러 총 6번의 버튼으로 0층까지 내려올 수 있다. - 어떤 조건의 상황에서 층 수를 올리는게 좋고 내리는게 좋을까? 두번째 입출력 예시인 2554를 통해 알아보자.
- 하나의 버튼을 누를 때 마다 하나의 마법의 돌을 사용하므로 아래부터는 버튼을 누르는 행위를 마법의 돌을 사용했다고 표현하겠다.
- 먼저 마법의 돌을 최소로 사용한 경우와 아닌 경우에서, 가장 끝 단위인 +1층, -1층 버튼부터 각 자리의 숫자가 5보다 크면 층 수를 올리고 숫자가 5보다 작다면 층 수를 내리고, 마지막으로 숫자가 5라면 다음 단위인 +10층, -10층 자리의 숫자를 봐서 해당 숫자가 5보다 같거다 크다면 올려주고, 5보다 작다면 내려주는게 맞는 판단이었다. 이해가 어려우니 아래 그림을 보자.
위 처럼 진행되면, 다음 차례인 100번대 자리의 숫자가 6이므로 마법의 돌을 4개를 사용해 올려주고, 마지막으로 3개를 더 사용해 내려주게 된다. 이렇게 하면 현재 7개를 더 사용했다. 만약 반대로 내려줬다면 마찬가지로 100번대 자리에서 5개를 사용하고, 마지막으로 두개를 추가해 사용함으로써 똑같은 결과인 7개를 추가로 사용하는 상황이지만, 지금 보고있는 상황은 가장 애매한 상황인 5가 중첩되어 나오는 경우이다. 일반적으로 5가 나왔지만 5가 중첩되지 않는 상황에서는 앞자리가 5이상이면 올려주는게 가장 최소루트이다.
- 예외없이 규칙을 모두 찾았다고 판단해서 코드로 해당 내용을 반복문을 통해 구현 후 호기롭게 테스트를 해봤지만, 통과/불통과가 섞여서 나왔다.
- 번뇌의 시간을 보내던 중 깨달음을 얻을 수 있었다. 현재 자리의 수가 5보다 클 때, 전 자리의 수를 1 더해주는 논리를 구현했지만 아래와 같은 상황이 발생할 수 있었다.
- 이처럼 현재 자리의 수가 5보다 크기 때문에 위로 올려주지만, 다음자리의 숫자에 1을 더해줄 때 10이 되버리는 경우가 발생할 수 있다.
- 원하는 결과는 자동으로 10 -> 0으로 바꿔주고 다시 또 그 전 자릿수에 1을 더해주는것이지만, 현재 이것까지 고려해서 코드를 작성하지 못했다는 것을 깨달았다.
- 따라서, 우선적으로 현재자릿수가 10인지 아닌지 판단해서 만약 10이라면 바로 위에 언급한 동작을 먼저 해주게끔 코드를 재구성했다.
- 솔루션
class Solution {
private int magicRock = 0; // 멤버변수
private int[] intToArrays(int storey) { // 정수형 입력값을 정수형 배열로 변환
String temp = Integer.toString(storey);
int[] digits = new int[temp.length()];
for (int i = 0; i < temp.length(); i++)
digits[i] = temp.charAt(i) - '0';
return digits;
}
private void checkDigitIsTen(int[] digits, int i) { // 동작구현 메소드
if(digits[i] != 10) {
if(digits[i] > 5) {
this.magicRock += 10 - digits[i];
digits[i - 1] += 1;
}
else if(digits[i] < 5) this.magicRock += digits[i];
else {
if(digits[i - 1] >= 5) {
this.magicRock += 10 - digits[i];
digits[i - 1] += 1;
} else this.magicRock += digits[i];
}
} else {
digits[i] = 0;
digits[i - 1] += 1;
}
}
public int solution(int storey) { // 메인 메소드
int[] digits = intToArrays(storey);
for(int i = digits.length - 1; i >= 0 ; i--) {
if(i != 0) checkDigitIsTen(digits, i);
else {
if(digits[0] > 5) this.magicRock += 10 - digits[0] + 1;
else this.magicRock += digits[0];
}
}
return this.magicRock;
}
}
- 배운점
- 이렇게 어떤 경우의 수를 판단해 규칙을 찾고 논리를 만들어야 되는 문제에서는 발생할 수 있는 모든 예외적인 상황을 사전에 미리 생각해보고 전체적인 그림을 그려나가야 한다.
- 놓친 부분이 있었다면, 현재 나의 머리속에는 '틀린 논리가 없을텐데,,?' 라는 생각이 들기 때문에 오히려 예외적인 상황을 발견하기 어려울 수 있을것이다.
- 복잡한 문제일수록 세세하게 예외적인 변수가 발생할 수 있을지 차분히 생각해보자!
'코딩테스트 > 프로그래머스' 카테고리의 다른 글
[Java] 프로그래머스 Level 2 : 올바른 괄호 (0) | 2023.06.08 |
---|---|
[Java] 프로그래머스 Level 2 : 124 나라의 숫자 (0) | 2023.06.02 |
[Java] 프로그래머스 Level 2: 문자열 압축 (0) | 2023.05.30 |
[Java] 프로그래머스 Level 1: 둘만의 암호 (0) | 2023.05.29 |
[Java] 프로그래머스 Level 1: 공원 산책 (5) | 2023.05.26 |