全排列

第Q个全排列

妖精的绣舞 提交于 2020-02-25 22:32:33
第Q个全排列 解题思路:全排列可以用dfs实现,但是循环输入明显会卡掉直接暴力取结果的算法,然后想想如果只需要知道第几个的话,其实手推也不难,因为每一位取第几个数取决于他处于当前状态下阶乘的几倍,代码实现如下: # include <bits/stdc++.h> using namespace std ; int num [ 10 ] [ 15 ] , n , cnt , sum , s [ 15 ] , vis [ 15 ] ; int main ( ) { for ( int i = 1 ; i <= 9 ; i ++ ) { num [ i ] [ i ] = 1 ; for ( int j = i - 1 , k = 1 ; j >= 1 ; j -- , k ++ ) { num [ i ] [ j ] = num [ i ] [ j + 1 ] * k ; } } while ( scanf ( "%d %d" , & n , & cnt ) != EOF ) { vector < int > v ; for ( int i = 1 ; i <= n ; i ++ ) { v . push_back ( i ) ; } for ( int i = 1 ; i <= n ; i ++ ) { int ans = 0 ; while ( cnt > num [ n ] [

字符串全排列问题

荒凉一梦 提交于 2020-02-09 00:44:07
问题:输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。 输入描述:输入一个字符串,长度不超过9(可能有字符重复),字符只包括大小写字母。 解决思路:第一遍将第一个字母固定,遍历所有字母,与第一个字母交换位置,然后固定下一个字母,与其后的所有字母依次交换位置,直到固定最后一个字母。 字符串的全排列是一个概率问题,排除相同字母造成的影响,比如abc的全排列个数为A 3 3 = 6个; 再比如字符串“YONYOU”,先拍出现一次的字母,再排出现两次的字母,一共是A 6 2C 4 2C 2 2,解释如下:有6个位置;先排N ,U有6*5=30种;再排Y,Y只有4个坑了有4*3/2=6种;最后2个位置给O,O,所以总共30*6=180种。 算法采用递归算法: 1 import java.util.ArrayList; 2 import java.util.Collections; 3 4 /** 5 * 输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。 6 * @author 王任义 7 * 8 */ 9 public class

剑指offer-字符串的排列

纵然是瞬间 提交于 2020-02-01 05:18:28
题目描述 输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。 输入描述: 输入一个字符串,长度不超过9(可能有字符重复),字符只包括大小写字母。 解题思路 此题目要求找出一个字符串的全排列,可以按照以下两步来递归的求解: 找到当前子字符串第一个字符的所有可能,可以通过将第一个字符依次与后面与其不相同的字符交换 固定第一个字符,找到后面所有字符的全排列 从字符串的第一个字符开始,按照上述步骤递归地向后交换并寻找全排列,当遍历到最后一个字符时,此时的字符串便是一种排列顺序,于是把当前字符串加入到vector容器中。 代码 1 class Solution { 2 public: 3 vector<string> v; 4 vector<string> Permutation(string str) { 5 if(str.size()) 6 Pmt(str,0); 7 return v; 8 } 9 void Pmt(string str,int f){ 10 if(f==str.size()-1) 11 v.push_back(str); 12 else{ 13 Pmt(str,f+1); 14 for(int i=f+1;i<str.size();i++){

全排列

旧街凉风 提交于 2020-01-28 04:41:25
全排列 全排列是将一组数按一定顺序进行排列,如果这组数有n个,那么全排列数为n!个。 1、设计一个递归算法生成n个元素{r1,r2,…,rn}的全排列(所有元素按不同顺序所有的组合)。 以{1, 2, 3, 4, 5}为例说明全排列的递归算法。 先看最后两个数4, 5。 它们的全排列为4 5和5 4, 即以4开头和5的全排列和以5开头和4的全排列。 再看后三个数3, 4, 5。它们的全排列为3 4 5、3 5 4、4 3 5、4 5 3、5 3 4、5 4 3 六组数。即以3开头和45的全排列的、以4开头和35的全排列和以5开头和34的全排列。 //全排列 (递归) # include <iostream> # include <algorithm> using namespace std ; int a [ 100 ] ; int cnt = 0 ; void swap ( int & x , int & y ) { //交换两个数的值 int t = x ; x = y ; y = t ; } void Perm ( int j , int n ) { //从第j个元素开始,共n个元素 if ( j == n ) { //排完了,打印输出 cnt ++ ; for ( int i = 0 ; i < n ; i ++ ) cout << a [ i ] ; cout <<

“回溯”算法总结(深度优先遍历 + 状态重置 + 剪枝)

自作多情 提交于 2020-01-15 03:54:03
地址:https://leetcode-cn.com/problems/permutations/solution/hui-su-suan-fa-python-dai-ma-java-dai-ma-by-liweiw/ 首先解释“回溯”算法的应用,“回溯”算法主要用于搜索,因此有时候“回溯算法”也叫“回溯搜索”。这里“搜索”的意思即“查找我们所需要的解”。我们每天使用的“搜索引擎”就是帮助我们在庞大的互联网上搜索我们需要的信息。 而这里的“回溯”指的是“状态重置”,可以理解为“回到过去”、“恢复现场”,是在编码的过程中,为了节约空间而使用的一种技巧。 下面我们通过一个非常经典的问题,介绍“回溯”算法在查找问题的解中的应用。 这是「力扣」上第 46 号问题:“全排列”,这道题给我们一个没有重复数字的数组,要求我们返回其所有可能的全排列。 例如给出的数组是 [1, 2, 3] ,这个数组所有可能的全排列如下: [ [1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1] ] 我们知道, N 个数字的全排列一共有 N ! N! N ! 这么多个。 大家可以尝试一下在纸上写 3 个数字、4 个数字、5 个数字的全排列,相信不难找到这样的方法。 例如数组 [1, 2, 3] 的全排列。 我们先写以 1 开头的全排列

全排列 next_permutation()函数

懵懂的女人 提交于 2019-12-19 23:46:17
擅长排列的小明 时间限制: 1000 ms | 内存限制: 65535 KB 难度: 4 描述 小明十分聪明,而且十分擅长排列计算。比如给小明一个数字5,他能立刻给出1-5按字典序的全排列,如果你想为难他,在这5个数字中选出几个数字让他继续全排列,那么你就错了,他同样的很擅长。现在需要你写一个程序来验证擅长排列的小明到底对不对。 输入 第一行输入整数N(1<N<10)表示多少组测试数据, 每组测试数据第一行两个整数 n m (1<n<9,0<m<=n) 输出 在1-n中选取m个字符进行全排列,按字典序全部输出,每种排列占一行,每组数据间不需分界。如样例 样例输入 2 3 1 4 2 样例输出 1 2 3 12 13 14 21 23 24 31 32 34 41 42 43 只是next_permutation()的简单应用而已 #include<stdio.h> #include<algorithm> #include<iterator> using namespace std; int main() { int n,M,N; int last[10]={0}; scanf("%d",&n); while(n--) { int a[10]={1,2,3,4,5,6,7,8,9}; scanf("%d%d",&M,&N); do { if(!equal(a,a+N,last)) {

12-2:(47)全排列 II

孤者浪人 提交于 2019-12-18 02:02:32
47. 全排列 II 给定一个可包含重复数字的序列,返回所有不重复的全排列。 示例: 输入: [1,1,2] 输出: [ [1,1,2], [1,2,1], [2,1,1] ] A neat python solution: class Solution(object): def permuteUnique(self, nums): """ :type nums: List[int] :rtype: List[List[int]] """ ans = [[]] for n in nums: ans = [p[:i]+[n]+p[i:] for p in ans for i in range((p+[n]).index(n)+1)] return ans 分析 : (1)代码每次仅将nums中的一个数字抽出来(而且是按顺序抽出来),将它插入已经排列好的结果当中,从而形成由这个新加入的数字引发的新的排列。不妨让 nums = [1, 1, 2] ,那么对每一轮外层 for 循环,ans 得到的结果如下所示: # 第1轮外层for循环:n = 1 ans = [[1]] # 第2轮外层for循环:n = 1 ans = [[1, 1]] # 第3轮外层for循环:n = 2 ans = [[2, 1, 1], [1, 2, 1], [1, 1, 2]] (2

全排列java

旧巷老猫 提交于 2019-12-11 06:55:09
定义: 从n个不同元素中任取m(m≤n)个元素,按照一定的顺序排列起来,叫做从n个不同元素中取出m个元素的一个排列。当m=n时所有的排列情况叫全排列。 公式:全排列数f(n)=n!(定义0!=1) 例如:求1、2、3、4、5、6、7、8、9的全排列 思路: 将开始的九个数中的第一个数逐个与所有数交换得到 1 2 3 4 5 6 7 8 9 2 1 3 4 5 6 7 8 9 3 2 1 4 5 6 7 8 9 4 2 3 1 5 6 7 8 9 5 2 3 4 1 6 7 8 9 6 2 3 4 5 1 7 8 9 7 2 3 4 5 6 1 8 9 8 2 3 4 5 6 7 1 9 9 2 3 4 5 6 7 8 1 忽略排好的第一列,对每一行剩下的8个数再进行相同操作,例如第一行,得到: 2 3 4 5 6 7 8 9 3 2 4 5 6 7 8 9 4 3 2 5 6 7 8 9 5 3 4 2 6 7 8 9 6 3 4 5 2 7 8 9 7 3 4 5 6 2 8 9 8 3 4 5 6 7 2 9 9 3 4 5 6 7 8 2 忽略排好的第一列,对每一行剩下的7个数再进行相同操作… 当第一个数和最后一个数重合时操作结束。 代码 import java . util . Arrays ; public class QuanPaiLie { public static

C++递归函数

巧了我就是萌 提交于 2019-12-08 09:26:06
C++递归函数 【递归,就是在运行的过程中调用自己】 比如:(点击了下面的递归,搜索结果还是递归) A.构成递归需具备的条件: 1.子问题须与原始问题为同样的事,且更为简单。 2.不能无限制的调用本身,必须有个出口,化简为非递归状况处理。 B.递归可以解决的问题: 阶乘、斐波那契数列、汉诺塔、杨辉三角的存取、字符串回文判断、字符串全排列、二分查找、树的深度求解 C.递归的过程(图片来源见水印,侵删) 【递归的过程可以理解为,把一个复杂的问题转化为一个个的小问题,而小问题能转化为更简单的问题,直到达到递归的“终点”——递归边界。递归边界是递归问题的特殊案例或者简单的情况,通过递归边界向上一层一层的返回数据,结束递归】 D.递归实例 Example ①://阶乘 #include <iostream> using namespace std; int Leo(int n) { int sum = 1; if(1 == n)//递归终止条件 { return 1; } sum =n * Leo(n - 1); return sum;//返回阶乘的总和 } int main() { int num; cin >> num;//输入一个数 cout << Leo(num) << endl; //输出该数的阶乘 return 0; } /* *在求X的阶乘和时 *可以利用递归的思想

C语言程序设计100例之(16):巧解算式

≯℡__Kan透↙ 提交于 2019-12-05 09:33:58
例16 巧解算式 问题描述 在1、2、3、4、5、6、7、8、9、10个数中间加上加号或减号,使得到的表达式的值为自然数N,如果中间没有符号,则认为前后为一个数,如1 2 3认为是一百二十三(123)。 例如:当N=100时,表达式值为100的填法有24种。123+4+5+67-89-10=100是一种填法,1+2+3+4+56+7+8+9+10=100也是一种填法。 编写一个程序,找出使表达式的值等于N的填写方法有多少种? 输入格式 输入包含多组测试数据。每组测试数据一个自然数n,占据独立一行。0表示输入结束。 输出格式 对每组测试数据,输出一行,即使表达式的值等于n的填写方法的种数。 输入样例 1 10 100 0 输出样例 45 26 24 (1)编程思路。 为了表示等式左边的算式,可以定义一个数组int a[20],其中元素a[0]、a[2]、…、a[16]分别保存数字1、2、…、9,a[18]和a[19]合起来保存数10。a[1]、a[3]、…、a[17]用0、1、2保存可能填写的运算符,其中0代表空格、1代表加号+、2代表减号 -。如下所示: 1 2 3 4 5 6 7 8 9 1 0 这样,可以用一个9重循环对9个空位可能填写的3种算符进行穷举,得到等式左边的算式,保存在数组a[20]中,然后对这个算式进行解析,若运算结果为N,则就是一种解法。