假设有从 1 到 n 的 n 个整数。用这些整数构造一个数组 perm(下标从 1 开始),只要满足下述条件 之一 ,该数组就是一个 BB美的排列 :
1.perm[i] 能够被 i 整除
2.i 能够被 perm[i] 整除
给你一个整数 n ,返回可以构造的 优美排列 的 数量 。
输入:n = 2
输出:2
解释:
第 1 个优美的排列是 [1,2]:
- perm[1] = 1 能被 i = 1 整除
- perm[2] = 2 能被 i = 2 整除
第 2 个优美的排列是 [2,1]:
- perm[1] = 2 能被 i = 1 整除
- i = 2 能被 perm[2] = 1 整除
根据题目,做过全排列的同学很快就能想出方法:
class Solution {
int sum = 0;
int n;
int[] arr;
int[] t;
boolean[] chak;
public int countArrangement(int h) {
n = h;
t = new int[n];
chak = new boolean[n];
dfs(0);
return sum;
}
private void dfs(int k) {
if (k == n) {
for (int i = 0; i < t.length; i++) {
int cot = t[i];
if (cot % (i + 1) != 0) {//判断
if((i+1) % cot != 0) {
break;
}
}
if(i==t.length-1) {
sum++;
}
}
}
for (int i = 0; i < t.length; i++) {
if (!chak[i]) {
chak[i] = true;
t[k] = i + 1;
dfs(k + 1);
chak[i] = false;
}
}
}
}
这个可以过60%,题目的数据达到了15,到12的时候就已经一时半会搜不出来了,所以我们要进行优化:同时判断同时搜索
class Solution {
boolean[] chak;
int n;
public int countArrangement(int h) {
n=h;
chak=new boolean[n+1];
return dfs(1);
}
private int dfs(int sum) {
int ans = 0;
if (sum > n) {// 到底了,符合条件
return 1;
}
for (int i = 1; i <= n; i++) {
if (!chak[i] && (i % sum == 0 || sum % i == 0)) {//因为它有两个条件,满足1 2,也可以满足2 1
chak[i]=true;
ans += dfs(sum + 1);
chak[i]=false;
}
}
return ans;
}
}
经过优化,我们减去了最后的判断数组,节约了很大一部分时间