美文网首页
【算法题】2741. 特别的排列

【算法题】2741. 特别的排列

作者: 程序员小2 | 来源:发表于2023-07-02 06:48 被阅读0次

    题目:

    给你一个下标从 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;
      }
    }
    

    相关文章

      网友评论

          本文标题:【算法题】2741. 特别的排列

          本文链接:https://www.haomeiwen.com/subject/ssxfudtx.html