题目
给定一个整数n,代表汉诺塔游戏中从小到大放置的n个圆盘,假设开始时所有的圆盘都放在左边的柱子上,想按照汉诺塔游戏的要求把所有的圆盘都移到右边的柱子上。实现函数打印最优移动轨迹。
进阶题目
给定一个整型数组arr,其中只含有1、2和3,代表所有圆盘目前的状态,1代表左柱,2代表中柱,3代表右柱,arr[i]的值代表第i+1个圆盘的位置。
如果arr代表的状态是最优移动轨迹过程中出现的状态,返回arr这种状态是最优移动轨迹中的第几个状态。如果arr代表的状态不是最优移动轨迹过程中出现的状态,则返回-1。
思路
最优移动过程分三步:
-
圆盘1~i-1从from移动到mid。
-
单独把圆盘i从from移动到to。
-
把圆盘1~i-1从mid移动到to。
另外:如果圆盘只有1个,直接把这个圆盘从from移动到to即可。
代码实现
public class Hanoi {
public void hanio(int n) {
if (n > 0) {
func(n, "left", "mid", "right");
}
}
public void func(int n , String from, String mid, String to) {
if (n == 1) {
System.out.println("move from" + from + " to " + to);
} else {
func(n - 1, from, to, mid);
func(1, from, mid, to);
func(n - 1, mid, from, to);
}
}
/**
* 进阶题目 递归解法
* @param arr 代表最优移动轨迹过程中出现的状态
* @return 当前是最优移动轨迹中的第几个状态
*/
public int step1(int[] arr) {
if (arr == null || arr.length == 0) {
return -1;
}
return process(arr, arr.length - 1, 1, 2, 3);
}
public int process(int[] arr, int i, int from, int mid, int to) {
if (i == -1) {
return 0;
}
if (arr[i] != from && arr[i] != to) {
return -1;
}
if (arr[i] == from) {
return process(arr, i - 1, from, to, mid);
} else {
int rest = process(arr, i - 1, mid, from, to);
if (rest == -1) {
return -1;
}
return (1 << i) + rest;
}
}
/**
* 进阶题目 非递归解法
* @param arr 代表最优移动轨迹过程中出现的状态
* @return 当前是最优移动轨迹中的第几个状态
*/
public int step(int[] arr) {
if (arr == null || arr.length == 0) {
return -1;
}
int from = 1;
int mid = 2;
int to = 3;
int i = arr.length - 1;
int res = 0;
int tmp = 0;
while (i >= 0) {
if (arr[i] != from && arr[i] != to) {
return -1;
}
if (arr[i] == to) {
res += 1 << i;
tmp = from;
from = mid;
} else {
tmp = to;
to = mid;
}
mid = tmp;
i--;
}
return res;
}