题目链接(力扣网):https://leetcode-cn.com/leetbook/read/interesting-algorithm-puzzles-for-programmers/9umkfd/
1.标了数字1~n的两幅牌,共2n张
2.两个1中间放1张牌;...;两个n中间放n张牌
求:当n=11时,求共有多少种排列方式
1.用容量为2n的集合List表示每个位置上的牌(排列方式)
2.循环遍历,在下标 i 和下标 (i+n+1) 位置上尝试放入两张数字n的牌
3.当集合List中不包含0时,表示放满了,即得到了一种正确的排列方式
4.统计正确排列方式的次数
public static void main(String[] args) {
int n = 11; // 一副牌的数字为[1,11]
List list = new ArrayList<>(2 * n); // 容量为两副牌的数量(2n)
list.addAll(Collections.nCopies(2 * n , 0)); // 全部初始化为0
System.out.println(put(n, list, 0)); // 输出共有多少种排列方式;put为自定义的方法
}
/**
* n 表示当前要放的是数字为n的牌
* list 表示2n个位置中已经放置的牌的情况
* count 表示截至目前为止,有效排列方式的数量
*/
public static int put(int n, List list, int count) {
// 递归出口
if (!list.contains(0)) { // 每个位置都有牌了
System.out.println(list); // 输出这一种正确的排列方式
return count + 1; // 有效排列方式+1
}
// 递归调用
for (int i = 0; i + n + 1 < list.size(); i++) {
// 判断位置i和位置(i+n+1)上是否空缺(这两个位置正好相隔n张牌)
if (list.get(i) == 0 && list.get(i + n + 1) == 0) {
// 在位置i和(i+n)上放置数字n牌
list.set(i, n);
list.set(i + n + 1, n);
count = put(n - 1, list, count);
// 恢复放置数字n牌之前的状态
list.set(i, 0);
list.set(i + n + 1, 0);
}
}
return count;
}
......此处省略部分结果......
[1, 3, 1, 8, 5, 3, 7, 9, 10, 11, 5, 4, 8, 6, 7, 2, 4, 9, 2, 10, 6, 11]
[2, 4, 7, 2, 8, 6, 4, 9, 10, 11, 7, 3, 6, 8, 5, 3, 1, 9, 1, 10, 5, 11]
[2, 3, 7, 2, 8, 3, 5, 9, 10, 11, 7, 6, 5, 8, 1, 4, 1, 9, 6, 10, 4, 11]
[5, 1, 7, 1, 6, 8, 5, 9, 10, 11, 7, 6, 2, 4, 8, 2, 3, 9, 4, 10, 3, 11]
[2, 4, 7, 2, 6, 8, 4, 9, 10, 11, 7, 6, 5, 1, 8, 1, 3, 9, 5, 10, 3, 11]
[3, 1, 7, 1, 3, 8, 5, 9, 10, 11, 7, 6, 5, 2, 8, 4, 2, 9, 6, 10, 4, 11]
[3, 1, 7, 1, 3, 8, 5, 9, 10, 11, 7, 4, 5, 6, 8, 2, 4, 9, 2, 10, 6, 11]
[1, 2, 1, 7, 2, 8, 6, 9, 10, 11, 4, 7, 5, 6, 8, 4, 3, 9, 5, 10, 3, 11]
[1, 4, 1, 7, 5, 8, 4, 9, 10, 11, 5, 7, 3, 6, 8, 2, 3, 9, 2, 10, 6, 11]
35584