这是我参与8月更文挑战的第16天,活动详情查看:8月更文挑战
526. 优美的排列
假设有从 1 到 N 的 N 个整数,如果从这 N 个数字中成功构造出一个数组,使得数组的第 i 位 (1 <= i <= N) 满足如下两个条件中的一个,我们就称这个数组为一个优美的排列。条件:
- 第 i 位的数字能被 i 整除
- 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 整除
说明:
- N 是一个正整数,并且不会超过15。
方法一
看一眼数据范围,n不会超过15,那么可以放心大胆的使用面向用例编程大法
首先在测试用例中分别输入
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
接着编写代码 -_-
class Solution {
public int countArrangement(int n) {
int[] ans = new int[]{0,1,2,3,8,10,36,41,132,250,700,750,4010,4237,10680,24679};
return ans[n];
}
}
方法二
递归加回溯:看一眼数据范围,n不会超过15,那么可以放心大胆的使用递归;
- 递归出口:当递归到第
u个数时,有u>n,说明1~n已经全部被用完且这条路径符合题意,答案加1,并返回; - 递归进入下一层的条件:当前这个数,在之前没有被使用,且符合题目中给的条件,即,要么这第
i个位置上的数能被i整除,要么这个第i个位置上的数,能够把i给整除;
class Solution {
int res = 0, n;
boolean[] st;
public int countArrangement(int _n) {
n = _n;
st = new boolean[n + 1];
dfs(1);
return res;
}
void dfs(int u) {
if (u > n) {
res ++;
return;
}
for (int i = 1; i <= n; i ++ ) {
if (!st[i] && (u % i == 0 || i % u == 0)) {
st[i] = true;
dfs(u + 1);
st[i] = false;
}
}
return ;
}
}