문자열의 조이스틱 좌우이동 최솟값 계산.
( 주의사항 ) 좌우이동의 최솟값 계산을 수행할 때 연속된 A의 개수
에 따라 최솟값이 달라지게 된다!
문자열의 조이스틱 상하이동 최솟값 계산.
좌우이동, 상하이동 최솟값을 더한 값 반환.
풀이 방법은 잘 떠올렸고, 상하이동 최솟값 알고리즘을 쉽게 구현하였으나 좌우이동 최솟값을 구하는 알고리즘을 구현하는데 애를 먹었다. (어려웠다고 생각한다. ㅠㅠ)
좌우이동의 최솟값을 계산할 때 가장 구현하기 어려웠던 부분이 있다. for문과 while문 안의 이 int move = 2 * i + name.length() - next;
부분이다. 풀이에 대해 좀 더 자세하게 설명하려 한다.
첫 번째로 int minMove = name.length() - 1;
을 선언해준다. 왜냐하면 왼쪽(정방향)으로 좌우이동할 경우의 최대값이기 때문이다.
다음 int move = 2 * i + name.length() - next;
에서 문자열 전체 길이(name.length())에서 연속된 A의 길이(next)를 빼준다.
--> A는 굳이 변경할 필요가 없으므로 위 연산을 통해 좌우이동을 안하는 것으로 간주하고 계산을 수행하게 된다!
그리고 2 * i를 더해주는 이유는 기존의 좌우이동 방향을 바꿔 탐색하는 경우를 계산해준다.
--> 즉 연속된 A가 있을 경우 최솟값을 구할 수 있고, 최악의 경우인 연속된 A가 없을 경우 최댓값이 나오게 된다.
예를 들어, JJJAAAN 경우에서 연속된 A가 있어 3번째 J에서 좌우이동 방향이 바뀌게 되고 N으로 가게 되어 최솟값 5가 계산된다. 이러한 계산을 수행하는 식이라고 생각하면 된다.
class Solution {
public int solution(String name) {
int answer = 0;
char[] names = name.toCharArray();
int minMove = name.length() - 1;
// 좌우 이동 부분 복습 요망!!
// 조이스틱 좌우이동 최솟값 구하기
for (int i = 0; i < name.length(); i++) {
if ((int) names[i] != 65) {
int next = i + 1;
while (next < name.length() && (int) names[next] == 65) {
next++;
}
int move = 2 * i + name.length() - next;
minMove = Math.min(move, minMove);
}
}
answer += minMove;
// 조이스틱 상하이동 최솟값 구하기
for (int i = 0; i < name.length(); i++) {
int front_a = Math.abs((int) names[i] - 65);
int end_z = Math.abs((int) names[i] - 90) + 1;
answer += Math.min(front_a, end_z);
}
return answer;
}
}