Suppose you have N integers from 1 to N. We define a beautiful arrangement as an array that is constructed by these N numbers successfully if one of the following is true for the ith position (1 ≤ i ≤ N) in this array:

  1. The number at the ith position is divisible by i.
  2. i is divisible by the number at the ith position.

Now given N, how many beautiful arrangements can you construct?

Example 1:

Input: 2
Output: 2
Explanation:

The first beautiful arrangement is [1, 2]:

Number at the 1st position (i=1) is 1, and 1 is divisible by i (i=1).

Number at the 2nd position (i=2) is 2, and 2 is divisible by i (i=2).

The second beautiful arrangement is [2, 1]:

Number at the 1st position (i=1) is 2, and 2 is divisible by i (i=1).

Number at the 2nd position (i=2) is 1, and i (i=2) is divisible by 1.

Note:

  1. N is a positive integer and will not exceed 15.

这道题给了我们1到N,总共N个正数,然后定义了一种优美排列方式,对于该排列中的所有数,如果数字可以整除下标,或者下标可以整除数字,那么我们就是优美排列,让我们求出所有优美排列的个数。那么对于求种类个数,或者是求所有情况,这种问题通常要用递归来做,递归简直是暴力的不能再暴力的方法了。而递归方法等难点在于写递归函数,如何确定终止条件,还有for循环中变量的起始位置如何确定。那么这里我们需要一个visited数组来记录数字是否已经访问过,因为优美排列中不能有重复数字。我们用变量pos来标记已经生成的数字的个数,如果大于N了,说明已经找到了一组排列,结果res自增1。在for循环中,i应该从1开始,因为我们遍历1到N中的所有数字,如果该数字未被使用过,且满足和坐标之间的整除关系,那么我们标记该数字已被访问过,再调用下一个位置的递归函数,之后不要忘记了恢复初始状态,参见代码如下:

解法一:

class Solution {
public:
int countArrangement(int N) {
int res = ;
vector<int> visited(N + , );
helper(N, visited, , res);
return res;
}
void helper(int N, vector<int>& visited, int pos, int& res) {
if (pos > N) {
++res;
return;
}
for (int i = ; i <= N; ++i) {
if (visited[i] == && (i % pos == || pos % i == )) {
visited[i] = ;
helper(N, visited, pos + , res);
visited[i] = ;
}
}
}
};

上面的解法在N=4时产生的优美序列如下:

1 2 3 4
1 4 3 2
2 1 3 4
2 4 3 1
3 2 1 4
3 4 1 2
4 1 3 2
4 2 3 1

通过看上面的分析,是不是觉得这道题的本质其实是求全排列,然后在所有全排列中筛选出符合题意的排列。那么求全排列的另一种经典解法就是交换数组中任意两个数字的位置,来形成新的排列,参见代码如下:

解法二:

class Solution {
public:
int countArrangement(int N) {
vector<int> nums(N);
for (int i = ; i < N; ++i) nums[i] = i + ;
return helper(N, nums);
}
int helper(int n, vector<int>& nums) {
if (n <= ) return ;
int res = ;
for (int i = ; i < n; ++i) {
if (n % nums[i] == || nums[i] % n == ) {
swap(nums[i], nums[n - ]);
res += helper(n - , nums);
swap(nums[i], nums[n - ]);
}
}
return res;
}
};

上面的解法在N=4时产生的优美序列如下:

2 4 3 1
4 2 3 1
3 4 1 2
4 1 3 2
1 4 3 2
3 2 1 4
2 1 3 4
1 2 3 4

参考资料:

https://discuss.leetcode.com/topic/79916/java-solution-backtracking

https://discuss.leetcode.com/topic/79921/my-c-elegant-solution-with-back-tracking

LeetCode All in One 题目讲解汇总(持续更新中...)

[LeetCode] Beautiful Arrangement 优美排列的更多相关文章

  1. [LeetCode] Beautiful Arrangement II 优美排列之二

    Given two integers n and k, you need to construct a list which contains n different positive integer ...

  2. LeetCode Beautiful Arrangement II

    原题链接在这里:https://leetcode.com/problems/beautiful-arrangement-ii/description/ 题目: Given two integers n ...

  3. LeetCode Beautiful Arrangement

    原题链接在这里:https://leetcode.com/problems/beautiful-arrangement/description/ 题目: Suppose you have N inte ...

  4. [Swift]LeetCode526. 优美的排列 | Beautiful Arrangement

    Suppose you have N integers from 1 to N. We define a beautiful arrangement as an array that is const ...

  5. 【LeetCode】526. Beautiful Arrangement 解题报告(Python & C++)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 日期 题目地址:https://leetcode.c ...

  6. LC 667. Beautiful Arrangement II

    Given two integers n and k, you need to construct a list which contains n different positive integer ...

  7. 526. Beautiful Arrangement

    Suppose you have N integers from 1 to N. We define a beautiful arrangement as an array that is const ...

  8. LeetCode:下一个排列【31】

    LeetCode:下一个排列[31] 题目描述 实现获取下一个排列的函数,算法需要将给定数字序列重新排列成字典序中下一个更大的排列. 如果不存在下一个更大的排列,则将数字重新排列成最小的排列(即升序排 ...

  9. LeetCode:字符串的排列【567】

    LeetCode:字符串的排列[567] 题目描述 给定两个字符串 s1 和 s2,写一个函数来判断 s2 是否包含 s1 的排列. 换句话说,第一个字符串的排列之一是第二个字符串的子串. 示例1: ...

随机推荐

  1. [日常] NOIP前集训日记

    写点流水账放松身心... 10.8 前一天考完NHEEE的一调考试终于可以开始集训了Orz (然后上来考试就迟到5min, GG) T1维护队列瞎贪心, 过了大样例交上去一点也不稳...T出翔只拿了5 ...

  2. JavaScript(第二十一天)【DOM元素尺寸和位置】

    学习要点: 1.获取元素CSS大小 2.获取元素实际大小 3.获取元素周边大小 本章,我们主要讨论一下页面中的某一个元素它的各种大小和各种位置的计算方式,以便更好的理解.   一.获取元素CSS大小 ...

  3. beta冲刺计划安排

    经过紧张的Alpha阶段,很多组已经从完全不熟悉语言和环境,到现在能够实现初步的功能.下一阶段即将加快编码进度,完成系统功能.强化软件工程的体会. 凡事预则立,在Beta开始前,以小组为单位,在敏捷冲 ...

  4. Hibernate之Hibernate的体系结构

    体系结构简图: 这是一张体系结构的简图,其中的hibernate.properties文件的作用相当于配置文件hibernate.cfg.xml XML Mapping对应的就是映射文件 XXXX.h ...

  5. 帧动画的创建方式 - 纯Java代码方式

    废话不多说,先看东西 帧动画的创建方式主要以下2种: * 用xml创建动画: * 纯Java代码创建动画:   本文内容主要关注 纯java代码创建帧动画 的方式: 用xml创建帧动画:http:// ...

  6. 大数据学习总结(5)参考elk技术架构

  7. SpringCloud的服务网关zuul

    演示如何使用api网关屏蔽各服务来源 一.概念和定义 1.zuul最终还是使用Ribbon的,顺便测试一下Hystrix断路保护2.zuul也是一个EurekaClient,访问服务注册中心,获取元数 ...

  8. window.open()参数详解及对浏览器的兼容性

    因为篇幅,window.open()浏览器的兼容性请点击 这里 Part1:参数详解 window.open(url,name,param) url:即将打开的子窗口的地址:比如 "http ...

  9. 移动端登录页面input获取焦点后页面布局及输入框上移的问题

    最近切微信页面的时候,发现移动端的登录页面,带输入框的那种,如图: 从页面本身来看没有什么问题,上传至测试服务器,用iphone访问也没有什么问题,但是当同事用Android手机获取焦点后,问题来了, ...

  10. centOs6.5配置jdk及其注意事项

    1.下载jdk1.7 百度云链接: https://pan.baidu.com/s/15vXLO2eV18eVvmt-R5jGnQ 密码: 1gd6 2.解压压缩包 通过终端在/usr/local下新 ...