세 개의 기둥이 존재함.
1번에 있는 n 개의 원판 → 3번 원판으로 “최소 횟수"로 옮길 거임.
( 사실 몇 번에서 몇번으로 이동하는지는 중요하진 않음 )이라고 생각했는데 result 형태가 원판을 이동시킨 이동 과정이라서 중요하다. from → to 로 이동하고, 이동 할 때 마다, extra 기둥이 달라진다.
예를들어 1 → 2, 1→ 3, 2→ 3
[ [1,2], [1,3], [2,3] ]
(1시간 30분.. )
3개의 기둥이 있는 하노이탑 문제 → “바닥에 있는 원반"을 뺄 수 있도록 만들어야 함. ( 규칙 상, 더 큰 원반이 위에 올 수는 없기 때문이다 )
1 ~ n-1 원판을 “다른 기둥" 에 옮겨두고
→ n 번 원판을 3번으로 이동
→ 다른 기둥에 있는 1~n-1 원판들도 3 번으로 이동하는 과정
이 필요 하다.
이 문제를 “재귀적"으로 풀려면 어떻게 해야할까?
// 대충 이런 식
void hanoi(int n, int from, int extra, int to) {
int[] move = new int[] { from, to } ;
hanoi( n - 1, from, extra ); // 1 ~ n 은 다른 기둥으로 옮겨두고
answert.append(move);
hanoi( n - 1, extra , to ) ; // 1 ~ n 은 이제 "다른기둥" -> to 기둥으로 옮긴다
}
import java.util.*;
class Solution {
List<int[]> orders = new ArrayList<>(); // 여기에 int[2] 를 추가 해 나간다
public int[][] solution(int n) {
int[][] answer = {};
hanoi(n, 1,2,3);
answer = orders.toArray(new int[orders.size()][]);
return answer;
}
// 1 ~ n 원판들을 기둥 from 으로부터 to 기둥으로 이동한다. 이 과정에서 나머지 기둥 extra 를 사용하게 되기에 이것도 전달해주어야함
private void hanoi(int target, int from, int extra, int to) {
int[] move = new int[]{from, to};
if (target == 1) {
orders.add(move);
return;
}
// 1 ~ n-1 원판들은 일단 extra 로 이동해 줘야 한다
hanoi(target-1, from, to, extra);
// n 번 원판은 to 로 이동 해 준다
orders.add(move);
// 1 + n -1 원판들을 extra -> to 로 이동해 준다
hanoi(target-1, extra, from, to);
}
}
public Object[] toArray() {
return Arrays.copyOf(elementData, size);
}
public static <T> T[] copyOf(T[] original, int newLength) {
return (T[]) copyOf(original, newLength, original.getClass());
}
@IntrinsicCandidate
public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {
@SuppressWarnings("unchecked")
// 비어있는 객체를 생성하고
T[] copy = ((Object)newType == (Object)Object[].class)
? (T[]) new Object[newLength]
: (T[]) Array.newInstance(newType.getComponentType(), newLength);
// original 에 있던 값들을 복사 한다
System.arraycopy(original, 0, copy, 0,
Math.min(original.length, newLength));
return copy;
}