본문 바로가기
Algorithm/프로그래머스 고득점 Kit

[그리디] 조이스틱- Java코드 ★★★

https://programmers.co.kr/learn/courses/30/lessons/42860

 

코딩테스트 연습 - 체육복

점심시간에 도둑이 들어, 일부 학생이 체육복을 도난당했습니다. 다행히 여벌 체육복이 있는 학생이 이들에게 체육복을 빌려주려 합니다. 학생들의 번호는 체격 순으로 매겨져 있어, 바로 앞번

programmers.co.kr

 

 

문제

 

 

이해

문제 설명이 조금어렵다.

이해가 중요하다.

 

AAA 시작해서 위아래로 알파벳이동은 하나씩 움직인다.

 

그리고 또다른 움직임인 커서이동이 있다.

커서이동은 문자열에 자리 이동이다.

 

첫번째 문자를 목표하는 값으로 셋팅하였으면,

다음 두번째 문자로 이동할 수 있다.

그런데 문제에서는 다음 두번째 문자는 이미 A이므로 좌측이동이아닌 우측이동으로 맨끝지점으로 한번에 간다.

즉, 알파벳이동과 별개로, 좌측으로 순회할지 우측으로 순회할지,

혹은 좌측을 가다가 되돌아갈지 우측으로 순회하다 되돌아갈지

 

A가 연속으로 나오는 지점에서

커서의 최소이동값을 구해봐야하는 문제이다.

 

포인트

알파벳의 이동은 어렵지 않다,

중요한건 커서의 이동이다.

 

 

 

풀이

알파벳이동과 커서의 이동을 독립적으로 구해줄 수 있다

class Solution {
	    public static int solution(String name) {
        return AlphaMove(name) + CurserMove(name);
    }
    public static int AlphaMove(String name){
        int min=0, val;
        for(char ch : name.toCharArray()){
            val = Character.getNumericValue(ch);
            min += Math.min(36 -val , val-10);
        }
        return min;
    }
    // 2번부터 A의 연속지점을 찾아 최소이동을 저장한다
    public static int CurserMove(String name){
        int len = name.length();
        int min = len-1;
        for (int i = 0; i < name.length(); i++) {
            int next=i+1; // A의 연속지점을 기록할 변수
            while(next < len && name.charAt(next) =='A') next++;
            min = Math.min(min, Math.min((i * 2) + len - next, (len - next)*2+i));
        }
//        System.out.println("cur : " + min);
        return min;
    }
}

AlphaMove, CurserMove 으로 각각의 최소 이동을 구해주었다.

 

AlphaMove이동에서 주의할점은 A는 10 , Z는 35이다.

뒤로이동하는 경우는 Z로 이동하는 시점부터 시작이므로 36값에서 빼주어야 한다.

 

CurserMove 는 기존의 min값을 이동값의 최대값인 len -1로 셋팅하고 시작해서

현재값과 커서이동의 최소값을 구해주면된다.

Math.min((i * 2) + len - next, (len - next)*2+i)

코드를 그림으로 표현해 보았다.