算法练习(1)—— 简单递归/回溯
2017-09-09 01:59
369 查看
算法练习(1)—— 简单递归/回溯
前言
算法课的一环。题目一般都是从leetcode里拿,希望自己在学习中能有所提升吧,也希望自己能坚持下去。习题
这次的例题是在Backtracking栏目里找的第一题。
标题为 526. Beautiful Arrangement
懒得点链接的同学就直接看我下面的搬运吧~
Description
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:
The number at the ith position is divisible by i.
i is divisible by the number at the ith position.
Now given N, how many beautiful arrangements can you construct?
Note
N is a positive integer and will not exceed 15.
Example
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.
思路与代码
1.首先理解一下题意,大概就是每个数放在对应的第i位,要么它能整除i,要么i能整除它。2.题目给了个N=2的样例,不太具有代表性,因此我列一个N=4的solution:
[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]
3.列出来之后,我的最直接的想法就是枚举法。题目要求
N <= 15,如果用纯粹的枚举,最多需要
15!步。所以在枚举的过程中需要剪枝,就是列出之前先判断是否符合 两个要求之一 。这样其实可以省去特别多的次数。
4.实际写出来的代码如下:
#include <set> class Solution { public: int countArrangement(int N) { int count = 0; std::set<int> restNum; for (int i = 1; i <= N; i++) restNum.insert(i); recurse(1, restNum, count, N); return count; } /** ** @param 当前递归所在的数组下标 i ** @param 当前递归所剩余的未使用的数字 restNum ** @param beautiful arrangement的个数,按引用传递 ** @param 最大数字 N */ void recurse(int i, set<int> restNum, int& count, int N) { // 递归结束条件 if (i == N) { int target = *restNum.begin(); if (target % i == 0 || i % target == 0) count++; else return; } if (i < N) { std::set<int>::iterator it = restNum.begin(); // 对于满足条件的数字进行枚举,依次放入 for (; it != restNum.end(); it++) { int target = *it; if (target % i == 0 || i % target == 0) { std::set<int> recurseSet(restNum); recurseSet.erase(target); recurse(i + 1, recurseSet, count, N); } } } } };
5.以上代码已通过。一开始用的vector,写到一半觉得删除元素不方便,改成了set,果然顺手许多~我觉得应该有更好的做法,有大神的话希望分享一下
相关文章推荐
- 回溯算法----简单练习全排列
- 单链表逆置的递归与非递归算法 [简单的小算法练习]
- 和菜鸟一起学算法之递归和分治简单实例
- 蓝桥杯 基础练习 Sine之舞 【递归简单运用】
- 算法小题(1)python递归小练习
- 简单算法练习--插入排序
- Java基于循环递归回溯实现八皇后问题算法示例
- 五类常见算法小记 (递归与分治,动态规划,贪心,回溯,分支界限法)
- 【算法数据结构Java实现】递归的简单剖析及时间复杂度计算
- 2018年全国多校算法寒假训练营练习比赛(第五场)B(简单线段树)
- 算法学习笔记之三:八皇后问题(递归、回溯)
- 简单的算法练习
- 一个数组算法题,利用递归-回溯求解
- 算法训练 s01串 (简单递归)
- 一天一个算法题-简单的-递归-猴子吃桃问题
- 递归与回溯,DFS及BFS的算法
- 算法练习4.Median of Two Sorted Arrays两个有序数组的中位数(递归、分治)
- 不使用 for , while ,递归,如何解决一道简单的算法题?
- 算法学习 八皇后问题的递归实现 java版 回溯思想
- 算法之递归练习