程序员的算法趣题:Q53 同数包夹(Java版)

题目说明

题目链接(力扣网):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

 

你可能感兴趣的:(力扣,算法,java)