문자열 "hello"에서 각 문자를 오른쪽으로 한 칸씩 밀고 마지막 문자는 맨 앞으로 이동시키면 "ohell"이 됩니다. 이것을 문자열을 민다고 정의한다면 문자열 A와 B가 매개변수로 주어질 때, A를 밀어서 B가 될 수 있다면 밀어야 하는 최소 횟수를 return하고 밀어서 B가 될 수 없으면 -1을 return 하도록 solution 함수를 완성해보세요.
테스트 케이스로 제공되는 문제뿐만 아니라 그 외의 케이스까지 통과할 수 있는지, 너무 지엽적인 사고로 문제를 푼 건 아닌지 생각하는 버릇을 가져야겠다고 느꼈다.
메모리를 아끼기 위한 목적으로 StringBuffer를 사용한 게 패인이었다. 코드가 좀 길긴 해도 발상 자체는 나쁘지 않았던 것 같은데, 정작 A의 변경 사항이 누적되지 않은 채로 인덱스만 바꾸었으니.. 예시처럼 1번만 문자열을 미는 경우는 통과했으나 그 외의 케이스에서는 에러가 났다. 결국 8문제 중 4문제만 통과해 코드 제출에 실패했고, 짧게 줄일겸 처음부터 다시 생각해 보았다.
class Solution {
public int solution(String A, String B) {
int answer = 0;
StringBuffer newA = new StringBuffer();
for(int i=A.length() - 1; i>=0; i--){
newA.append(A.charAt(i));
newA.append(A.substring(0, A.length() - 1));
if(newA.toString().equals(B)){
answer = A.length() - i;
break;
}else{
newA.setLength(0);
}
}
if(newA.length() == 0 && !A.equals(B)) answer = -1;
return answer;
}
}
우선 hello -> ohell -> lohel과 같이 A의 변경 사항이 계속 반영될 수 있도록 메모리가 조금 더 사용되더라도 String을 쓰기로 했다. (버퍼를 써도 되지만 코드가 더 번잡할 것 같았다.)
그리고 루프를 거꾸로 돌 필요도 없었다. i를 인덱스로 안 쓰면 그만인 거 아닌가. subString()이라는 함수를 생각했으면서 왜 더 간단한 방법을 떠올리지 못했는지 의문..
변경사항이 newA에 계속 누적되므로 우리가 밀어야 할 문자는 마지막 인덱스, 그 외 나머지는 subString()으로 잘라내어 마지막 인덱스였던 문자 뒤에 붙여 주면 된다. 고정이라는 이야기다.
그렇다면 iterator는 무엇을 의미할까 바로 민 횟수다. 따라서 문자열을 밀어 새로 만들어낸 문자열 newA가 B와 equals()이라면, i를 바로 return 하도록 했다. 그리고 삼항 연산자를 활용해 변경 전인 A와 B가 equals()이라면 0을 그렇지 않다면 -1을 return 했다.
class Solution {
public int solution(String A, String B) {
String newA = A;
for (int i = 1; i < A.length(); i++) {
newA = newA.charAt(newA.length() - 1) + newA.substring(0, newA.length() - 1);
if (newA.equals(B)) {
return i;
}
}
return (A.equals(B)) ? 0 : -1;
}
}
