今天被问到LandFordPair序列,要求实现输入任意n,输出存在的序列种类,之前对于n皇后这类的算法写的少,所以当场一脸懵。特意在此记录下来。
一个序列f(n)拥有2*n个数,满足如下条件: 1、 1...n,每个数都出现且仅出现两次 2、 其中任意数k,在序列中出现的两个位置,之间有k个其他数 实现算法,对于输入的任意n,输出存在的landFord序列 例如输入3,输出 [3, 1, 2, 1, 3, 2] [2, 3, 1, 2, 1, 3]
分析一下,其实也挺简单的,模型上是填充一个Integer[2*n]的数组,假如数字k填充在下标i,那么下标i+k+1也必须填充k,也就是传说中的剪枝思路。只要尝试把n...1所有数都分配下去,那就是一个满足条件的序列。
Talk is cheap. Show me the code! ^_^
public class LandFordPair {
private static List<List<Integer>> pairs = Lists.newArrayList();
public static void main(String[] args) {
landFord(3);
}
private static void landFord(int n) {
Integer[] a = new Integer[2 * n];
assign(n, a);
pairs.forEach(System.out::println);
}
private static void assign(int k, Integer a[]) {
// k为0表示所有数字都分配好了,将结果记录到pairs
if (k == 0) {
pairs.add(Lists.newArrayList(a));
return;
}
for (int i = 0; i < (a.length - k - 1); i++) {
if (a[i] == null && a[i + k + 1] == null) {
// 尝试分配k的位置
a[i] = a[i + k + 1] = k;
// 递归分配k-1的位置
assign(k - 1, a);
// 抹掉此次分配回退,继续迭代尝试其他的分配方式
a[i] = a[i + k + 1] = null;
}
}
}
}