코딩테스트/Programmers

[JAVA] 키패드 누르기

hxx_1 2024. 5. 13. 14:55

< 내 풀이 >

class Solution {
    static char arr[][]={{'1','2','3'},{'4','5','6'},{'7','8','9'},{'*','0','#'}};
    static int distance(char start, int num){ // 현재 누르는 번호까지의 거리를 구하는 함수 
        int start_x=0,start_y=0;
        int end_x=0,end_y=0;
        
        for(int i=0;i<arr.length;i++){
            for(int j=0;j<arr[i].length;j++){
                if(arr[i][j]==start){
                    start_x=i;
                    start_y=j;
                }
                
                if(arr[i][j]==(char)num+'0'){
                    end_x=i;
                    end_y=j;
                }
            }
        }
     
        int dist=Math.abs(end_x-start_x)+Math.abs(end_y-start_y);
        return dist;
    }
    public String solution(int[] numbers, String hand) {
        String answer = "";
        char left='*'; //현재 왼손의 위치
        char right='#'; //현재 오른손의 위치
        
        for(int i=0;i<numbers.length;i++){
            if(numbers[i]==1||numbers[i]==4||numbers[i]==7){
                left=(char)(numbers[i]+'0');
                answer+="L";
            }
            else if(numbers[i]==3||numbers[i]==6||numbers[i]==9){
                right=(char)(numbers[i]+'0');
                answer+="R";
            }
            else { //누르는 숫자가 2,5,8,0 일 때 
                int right_dist= distance(right,numbers[i]);
                int left_dist=distance(left,numbers[i]);
                
                    
                if(right_dist==left_dist){
                    hand=hand.toUpperCase();
                    answer+=hand.charAt(0);
                    
                    if(hand.charAt(0)=='R')
                        right=(char)(numbers[i]+'0');
                    else
                        left=(char)(numbers[i]+'0');
                }
                else if(right_dist<left_dist){
                    right=(char)(numbers[i]+'0');
                    answer+="R";
                }
                
                else{
                    left=(char)(numbers[i]+'0');
                    answer+="L";
                }
                
            }
                
        }
        return answer;
    }
}

 

✏️ 풀이 방법

 

1. numbers 배열의 크기만큼 반복문을 돈다. ( 처음 왼손의 위치는 *, 처음 오른손의 위치는 # 이다.)

2. 번호가 1,4,7 일 경우 : 왼손의 위치 갱신, 정답을 저장하는 문자열에 "L" 추가

    번호가 3,6,9 일 경우: 오른손의 위치 갱신, 정답을 저장하는 문자열에 "R" 추가

    번호가 2,5,8,0 일 경우: (오른손 ~ 누르는 번호까지의 거리), (왼손 ~ 누르는 번호까지의 거리) 중 값이 작은 손으로 번호를 눌러야함

    => distance 함수 ( start 에서 num 까지의 거리를 구함) 

         1. 2차원 배열에 키패드의 값이 저장되어 있음

         2. 매개변수로 받은 start의 위치를 찾아 start_x 와 start_y 에 저장

         3. 매개변수로 받은 num의 위치를 찾아 end_x 와 end_y 에 저장

         4. Math.abs(end_x-start_x)+Math.abs(end_y-start_y) 가 곧 두 값의 거리가 된다. (Math.abs => 절댓값을 구하는 함수) 

             - 오른손에서의 거리와 왼손에서의 거리가 같을 때 : 매개변수로 받았던 hand 의 값을 대문자로 변환한 후, 첫 문자를

                answer 에 저장, R일 경우에는 오른손의 위치 갱신, L일 경우에는 왼손의 위치 갱신

            - 오른손에서의 거리 < 왼손에서의 거리 : 오른손의 위치 갱신, 정답을 저장하는 문자열에 "R" 추가

            - 왼손에서의 거리 < 오른손에서의 거리:  왼손의 위치 갱신, 정답을 저장하는 문자열에 "L" 추가

3. 위의 방법으로 구한 answer을 반환 

 

< 다른 사람의 풀이 >

class Solution {
    public String solution(int[] numbers, String hand) {
        StringBuilder sb = new StringBuilder();

        int left = 10;
        int right = 12;

        for (int i = 0; i < numbers.length; i++) {
            int n = numbers[i];

            if (n == 1 || n == 4 || n == 7) {
                left = n;
                sb.append("L");
            }
            if (n == 3 || n == 6 || n == 9) {
                right = n;
                sb.append("R");
            }
            if (n == 2 || n == 5 || n == 8 || n == 0) {
                if( n == 0 ) n = 11;

                int leftDiff = (Math.abs(n - left) / 3) + (Math.abs(n - left) % 3);
                int rightDiff =(Math.abs(n - right) / 3) + (Math.abs(n - right) % 3);

                if (leftDiff == rightDiff) {
                    if (hand.equals("right")) {
                        right = n;
                        sb.append("R");
                    }else{
                        left = n;
                        sb.append("L");
                    }
                } else if (leftDiff > rightDiff) {
                    right = n;
                    sb.append("R");
                } else {
                    left = n;
                    sb.append("L");
                }
            }
        }
        return sb.toString();
    }
}

 

➡️ 이와 같은 방법으로 n부터 left 까지의 거리, n부터 right 까지의 거리를 구하는게 너무 똑똑한 방법인 것 같다. 

 

✍🏻 느낀점

 

처음에 이 문제를 봤을 때, 거리를 어떻게 구해야할지 감이 잘 안잡혔다. 좀 생각을 해보고 2차원 배열에 값을 저장해서 풀었는데, 다른 사람의 풀이를 보고 나서 나는 왜 저 생각을 못했을까 싶었다. 또 하나 배우게 된 문제였다. 그리고 처음에 계속 답이 이상하게 나왔는데, 오른손에서의 거리와 왼손에서의 거리가 같을 때 answer에 값을 추가하고 난 후, 왼손과 오른손의 위치를 적절하게 바꿔주지 않아서 답이 계속 이상했다. 역시 문제를 꼼꼼하게 풀어야하는 것 같다. 거리 구하는 것만 잘하면 어렵지 않은 문제 같은데, 내가 처음에 너무 어렵게 생각하지 않았나싶다. 이번 문제로 또 하나 배웠으니 다음에 비슷한 문제가 나오면 겁 먹지 말자 ! 

 

 

 

참고 블로그


https://dding9code.tistory.com/75  //풀이 출처