leetcode-优美的排列

Posted 土豆烧鸡

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了leetcode-优美的排列相关的知识,希望对你有一定的参考价值。

假设有从 1 到 N 的 N 个整数,如果从这 N 个数字中成功构造出一个数组,使得数组的第 i 位 (1 <= i <= N) 满足如下两个条件中的一个,我们就称这个数组为一个优美的排列。条件:

  1. 第 i 位的数字能被 i 整除
  2. i 能被第 i 位上的数字整除

现在给定一个整数 N,请问可以构造多少个优美的排列?

示例1:

输入: 2
输出: 2
解释: 

第 1 个优美的排列是 [1, 2]:
  第 1 个位置(i=1)上的数字是1,1能被 i(i=1)整除
  第 2 个位置(i=2)上的数字是2,2能被 i(i=2)整除

第 2 个优美的排列是 [2, 1]:
  第 1 个位置(i=1)上的数字是2,2能被 i(i=1)整除
  第 2 个位置(i=2)上的数字是1,i(i=2)能被 1 整除

说明:

  1. N 是一个正整数,并且不会超过15。

参考博客:Beautiful Arrangement

方法1: 

思路: 对全排列进行改造。 void  dfs函数变为int dfs 函数。

现在 int dfs()函数的伪代码如下:

int dfs(int len){
    if(len==某个数){
        return 1;
    }
    int res=0;
    循环过程——————{
        res+= dfs(len+1,);
    }
    return res;
}

 

同时因为是通过筛选,因此在交换过程中加入判断条件,代码如下:

JAVA

class Solution {
    public int countArrangement(int N) {
        int[] nums=new int[N];
        for(int i=0;i<N;i++){
            nums[i]=i+1;
        }
        return dfs(nums,0);
    }
      public void swap(int[] nums,int i,int j){
        int temp=nums[i];
        nums[i]=nums[j];
        nums[j]=temp;
    }
    //DFS返回的是int类型。
    public int dfs(int[] nums,int len){
        if(len==nums.length){
            return 1;       //只要能够进行到回溯的终止条件,也就是出现了符合的排列,结果+1.
        }
        int res=0;  
        for(int i=len;i<nums.length;i++){
            //nums[i]  num[len] 进行交换,由于Len可能是0,因此+1.这里nums[len]%(i+1)==0反而不成立!
            if(nums[len]%(len+1)==0||(len+1)%nums[i]==0){
                swap(nums,i,len);
                res+=dfs(nums,len+1);
                swap(nums,i,len);
            }
        }
        return res;
    }
}

c++:

class Solution {
public:
    int dfs(vector<int>& nums,int len){
        if(len==nums.size()){
            return 1;
        }
        int res=0;
        for(int i=len;i<nums.size();i++){
            if(nums[i]%(len+1)==0||(len+1)%nums[i]==0){
                swap(nums[i],nums[len]);
                res+=dfs(nums,len+1);
                swap(nums[i],nums[len]);
            }
        }
        return res;
    }
    int countArrangement(int N) {
        vector<int> nums(N);
        for(int i=0;i<N;i++)nums[i]=i+1;
        return dfs(nums,0);
    }
};

方法2:

class Solution {
public:
    //思路:对每一位从1-N的数字进行判断,比如1 2 3 4 5 .
    //一号位可以放置:1 2 3 4 5.二号位可以放置:1 2 4  三号位只能放置:3  四号位可以放置1 2 4 
    //同时已经放置过的数字不能再使用了,用vis[i]==1来表示。
    //判断的条件为:if(vis[i]==0&&(i%len==0||len%i==0))
      int countArrangement(int N) {
        int count=0;
        vector<int> vis(N+1,0);
        dfs(count,N,vis,1);
        return count;
    }
    void dfs(int& count,int N,vector<int>& vis,int len){
            if(len>N){
                count++;
                return;
            }
        for(int i=1;i<=N;i++){
            if(vis[i]==0&&(i%len==0||len%i==0)){
                vis[i]=1;
                dfs(count,N,vis,len+1);
                vis[i]=0;
            }
        }
    }
  
};

 

以上是关于leetcode-优美的排列的主要内容,如果未能解决你的问题,请参考以下文章

LeetCode 0667. 优美的排列 II - 思维 + 构造

LeetCode 576. 出界的路径数(动规) / 526. 优美的排列(全排列,状压dp)

LeetCode 667 优美的排列II[数学] HERODING的LeetCode之路

LeetCode 526 优美的排列[dfs 回溯] HERODING的LeetCode之路

LeetCode 667. 优美的排列 II Beautiful Arrangement II (Medium)

优美的排列--回溯解决