全排列 以你之姓@ 2022-07-17 15:25 256阅读 0赞 # 全排列 # 给出一个字符串或整数数组,对这个字符串或整数数组进行全排列 例如:\{1, 2, 3\} 数组,对这个整数数组进行全排列。 # 递归实现 # ## 实现 ## /* * 递归输出序列的全排列 */ void FullArray(char* array, size_t array_size, unsigned int index) { if(index >= array_size) { for(unsigned int i = 0; i < array_size; ++i) { cout << array[i] << ' '; } cout << '\n'; return; } for(unsigned int i = index; i < array_size; ++i) { swap(array[i], array[index]); FullArray(array, array_size, index + 1); swap(array[i], array[index]); } } // Test int main() { int array[] = { 1, 2, 3}; fullArray(array, sizeof(array)/sizeof(array[0]), 0); } // 打印结果 1 2 3 1 3 2 2 1 3 2 3 1 3 2 1 3 1 2 ## 蕴含的思想 ## ### 分治法思想 ### 1. 问题的规模缩小到一定的程度就可以容易地解决。 2. 问题可以分解为若干个规模较小的相同问题,即该问题有**最优子结构** \[2\]性质。 3. 利用该问题分解出的子问题的解可以合并为该问题的解。 4. 该问题所分解出的各个子问题是相互独立的,即自问之间不包含公共子问题。 分治法的三个步骤: 1. 分解(Divide):将原问题分解为若干子问题,这些子问题都是原问题规模较小的实例。 2. 解决(Conquer):递归地求解各子问题。如果子问题规模足够小,则直接求解。 3. 合并(Combine):将所有子问题的解合并为原问题的解。 ## 分治在全排列中的应用 ## ### 问题: ### array = \{1, 2, 3, … n \}的全排列,心算手写非常简单,但是编写程序却无从下手。 ### 分析过程: ### 1. 如对array = \{1, 2, 3, … , n\} 数组进行全排列,可以先确定数组索引为 0 位置上的数字,然后再确定其他索引位置上的数字。 2. 划分成了两个子问题: 1. 确定`array数组索引0` 位置上数字全排列问题 2. 确定`array数组索引1~索引n-1`位置上数字的全排列子问题 3. 很明显,这里划分成了两个与原问题相同的子问题 4. 注意的是,划分子问题有很强的依赖性,即必须先解决`array数组索引0` 位置上数字全排列问题,然后才能解决`array数组索引1~索引n-1`位置上数字的全排列子问题 3. 确定`array数组索引0`位置上的数字是一个规模较小的子问题 // 解决数组索引0位置上的数字 // 注:原array索引为0位置上的数字当然可以为全排列的首数字 for (int i = 0; i < array_size; i++) { swap(array[i], array[0]); } // 同理确定`索引index`位置上的数字,但注意,i之前位置上的数字必须已经确定 for (int i = index; i < array_size; i++) { swap(array[i], array[index]); } 4. 确定`array数组索引1~索引n-1`位置上数字全排列,同理可继续按照上面的方式划分子问题:即`array数组索引1`位置上数字的全排列问题和`array数组索引2~索引n-1`位置上数字的全排列问题。 5. 每次确定`array数组索引index`(index:0~n-1)位置上的数字之后,`array数组index+1~n-1`位置上的数字也确定之后,必须恢复原数组的模样,之后给`array数组索引index`位置上确定新的数字时,确保原数字数组没有被打乱(因为直接使用了swap方式修改了index位置的值)。 for (int i = index; i < array_size; i++) { swap(array[i],array[index]); fullArray(array, array_size, index+1); swap(array[i], array[index]); } -------------------- 注:2016.11.1补充 # 有重复字符的全排列 # ## 去重复字符的递归算法 ## 例如:1223的全排列 1 - 223 2 - 123 3 - 221 带重复字符的全排列就是每个字符分别与它后面`非重复出现的字符`交换。即:第 i 个字符(前)与第 j 个字符(后)交换时,要求\[i, j)中没有与第 j 个字符相等的数。 bool isDuplicate(int* a, int lo, int hi) { while (lo < hi) { if (a[lo] == a[hi]) return true; lo++; } return false; } void Permutation(int* a, int size, int index) { if (index == size) { for (int i = 0; i < size; i++) cout << a[i] << endl; return; } for (int i = index; i < size; i++) { if (isDuplicate(a, index, i)) continue; swap(a[i], a[index]); Permutation(a, size, index+1); swap(a[i], a[index]); } } ## 重复数字的全排列递归算法时间复杂度 ## 记`Permutation函数`的时间复杂度函数为f(n),n为问题规模 则 f(n) = nf(n-1) + n^2 # 非递归实现 # # 参考资料 # \[1\] [Divide and Conquer - 分治法][Divide and Conquer -] \[2\] [什么是动态规划?动态规划的意义是什么?][Link 1] \[3\] [时间复杂度][Link 2] [Divide and Conquer -]: http://algorithm.yuanbin.me/zh-hans/basics_algorithm/divide_and_conquer.html [Link 1]: https://www.zhihu.com/question/23995189 [Link 2]: http://blog.csdn.net/booirror/article/details/7707551/
相关 排列2 全排列 <table> <tbody> <tr> <td> <h2>排列2</h2> <strong>Time Limit: 1000/1000 MS (Java/O 小咪咪/ 2024年02月18日 22:39/ 0 赞/ 74 阅读
相关 全排列 问题描述:设有\{r1,r2,...,rn\}共n个元素,这n个元素中可能存在重复元素,试设计一个算法,列出这n个元素的不同排列。 参考代码: inclu 电玩女神/ 2022年08月05日 02:54/ 0 赞/ 230 阅读
相关 全排列 全排列 给出一个字符串或整数数组,对这个字符串或整数数组进行全排列 例如:\{1, 2, 3\} 数组,对这个整数数组进行全排列。 递归实现 实现 以你之姓@/ 2022年07月17日 15:25/ 0 赞/ 257 阅读
相关 全排列 标题:带分数 100 可以表示为带分数的形式:100 = 3 + 69258 / 714 还可以表示为:100 = 82 + 3546 / 197 注意特征:带分数 今天药忘吃喽~/ 2022年06月18日 09:51/ 0 赞/ 212 阅读
相关 全排列 方法一:采用递归的方式例子1、将数组int arr\[4\]=\{1,2,3,4\}进行全排列 static int n = 0; void Perm( ﹏ヽ暗。殇╰゛Y/ 2022年06月17日 06:19/ 0 赞/ 248 阅读
相关 全排列 题目描述 给定一个没有重复数字的序列,返回其所有可能的全排列。 示例: 输入: [1,2,3] 输出: [ [1,2,3], 以你之姓@/ 2022年04月25日 06:54/ 0 赞/ 249 阅读
相关 全排列 全排列是将一组数按一定顺序进行排列,如果这组数有n个,那么全排列数为n!个。现以\{1, 2, 3, 4, 5\}为 例说明如何编写全排列的递归算法。 1、首先看 男娘i/ 2022年03月19日 01:50/ 0 赞/ 293 阅读
相关 全排列 给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。 给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。 示例: 输入:"23" 输 约定不等于承诺〃/ 2022年02月15日 00:47/ 0 赞/ 314 阅读
相关 全排列 talk is cheap, show me the code. public static void permutation(char[]ss,int i){ 蔚落/ 2022年01月29日 04:55/ 0 赞/ 333 阅读
还没有评论,来说两句吧...