【算法题】2741. 特别的排列
2023-07-02 本文已影响0人
程序员小2
题目:
给你一个下标从 0 开始的整数数组 nums ,它包含 n 个 互不相同 的正整数。如果 nums 的一个排列满足以下条件,我们称它是一个特别的排列:
对于 0 <= i < n - 1 的下标 i ,要么 nums[i] % nums[i+1] == 0 ,要么 nums[i+1] % nums[i] == 0 。
请你返回特别排列的总数目,由于答案可能很大,请将它对 109 + 7 取余 后返回。
示例 1:
输入:nums = [2,3,6]
输出:2
解释:[3,6,2] 和 [2,6,3] 是 nums 两个特别的排列。
示例 2:
输入:nums = [1,4,3]
输出:2
解释:[3,1,4] 和 [4,1,3] 是 nums 两个特别的排列。
提示:
2 <= nums.length <= 14
1 <= nums[i] <= 10^9
java代码:
class Solution {
public int specialPerm(int[] nums) {
int mod = (int) 1e9 + 7;
int dp[][] = new int[1 << nums.length][nums.length ];
// dp[u][j] := 当前集合为u,最后一次选择为j时的 特殊排列方案数
for (int i = 0; i < nums.length; i++) {
// 选择i后,集合中增加i
dp[1 << i][i] = 1;
}
for (int u = 0; u < 1 << nums.length; u++) {
// 考虑当前集合为u时,加入新的数到集合中
for (int j = 0; j < nums.length; j++) {
// 集合u中不存在j时,j才能加入集合
if ((u >> j & 1) == 0) {
// 判断上一个选择的数k是否与j满足题意要求
for (int k = 0; k < nums.length; k++) {
// k不在集合中时 说明上一个数选择的数不可能是k
if((u & 1 << k) > 0) {
// k和j满足题意要求时才能形成特殊排列
if ((nums[j] % nums[k] == 0 || nums[k] % nums[j] == 0)) {
dp[u | 1 << j][j] = (dp[u | 1 << j][j] + dp[u][k]) % mod;
}
}
}
}
}
}
int sum = 0;
// 集合为nums,遍历最后一次选择的数
for (int j = 0; j < nums.length; j++) {
sum = (sum + dp[(1 << nums.length) - 1][j]) % mod;
}
return sum;
}
}