【算法题】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;
  }
}
上一篇下一篇

猜你喜欢

热点阅读