【IT专家】实现全排列的两种算法:字典序列法以及递归算法(java)
- 格式:docx
- 大小:12.19 KB
- 文档页数:2
java 全组合算法思路
在Java中,实现全组合算法的思路有很多种,下面列举两种常见的思路:
解法一:递归实现全排列算法。
输入一串字符,然后对字符进行全排列,如“abc”,全排列结果为:"abc","acb","bac","bca","cab","cba"。
具体步骤如下:
1. 从字符串中选择一个作为第一个字符,然后对剩下的字符串进行全排列,如此递归下去,直到打印出全部排列。
2. 如:"abc":
- 选a作为第一个字符:”abc“,”acb“;
- 选b作为第一个字符:”bac“,”bca“;
- 选c作为第一个字符:”cab“,”cba“。
解法二:从大到小排序算法。
将字符串从小到大倒排序,以此得到整体的最小顺序,然后找到次小顺序,直到得到最大顺序,也就是从大到小的顺序。
找下一个顺序的算法如下:
1. 假设到了”21543“,从后往前找到i-1位置小于i位置的下标,1<5,所以要找的下标pos=1。
2. 将下标为1的数字1,和它后面最小的且大于它的数替换,”21543”---> "23541"。
3. 然后再将下标1后面的字符串翻转得到:"23145",这就得到了“21543”下一个顺序值“23145”。
需要注意的是,全组合算法的时间复杂度至少为$n!$级别,因此在处理大规模数据时可能会比较耗时。
在实际应用中,你需要根据具体需求选择合适的算法和实现方式。
java全排列递归算法全排列是指将一组元素按照一定的顺序进行排列,使得每个元素都能够出现在每个位置上,且每个元素只能出现一次。
在Java中,可以使用递归算法来实现全排列。
递归算法是一种通过调用自身来解决问题的方法。
在全排列问题中,可以通过递归的方式来生成所有可能的排列。
首先,我们需要定义一个递归函数,该函数接受一个数组和两个整数作为参数。
其中,数组表示待排列的元素,第一个整数表示当前排列的起始位置,第二个整数表示当前排列的结束位置。
在递归函数中,我们首先判断当前排列是否已经完成。
如果起始位置等于结束位置,说明已经完成了一次排列,我们可以将当前排列输出。
否则,我们需要对当前排列进行递归调用。
在递归调用中,我们需要将当前排列的起始位置与结束位置进行交换,然后对剩余的元素进行递归调用。
递归调用完成后,我们需要将当前排列的起始位置与结束位置进行交换,以便进行下一次排列。
下面是一个使用递归算法实现全排列的Java代码示例:```javapublic class Permutation {public static void permute(int[] nums, int start, int end) {if (start == end) {for (int num : nums) {System.out.print(num + " ");}System.out.println();} else {for (int i = start; i <= end; i++) {swap(nums, start, i);permute(nums, start + 1, end);swap(nums, start, i);}}}public static void swap(int[] nums, int i, int j) { int temp = nums[i];nums[i] = nums[j];nums[j] = temp;}public static void main(String[] args) {int[] nums = {1, 2, 3};permute(nums, 0, nums.length - 1);}}```在上述代码中,我们定义了一个`permute`函数来实现全排列。
解决不重复序列的全排列问题的两个方法:递归和字典序法简介
给定{1, 2, 3, , , n},其全排列为n! 个,这是最基础的高中组合数学知识。
我们以n=4 为例,其全部排列如下图(以字典序树形式来呈现):
我们很容易想到用递归来求出它的所有全排列。
仔细观察上图,
以1 开头,下面跟着{2, 3, 4} 的全排列;
以2 开头,下面跟着{1, 3, 4} 的全排列;
以3 开头,下面跟着{1, 2, 4} 的全排列;
以4 开头,下面跟着{1, 2, 3} 的全排列。
代码如下:
/**
*
* author : 刘毅(Limer)
* date : 2017-05-31
* mode : C++++
*/
#include
#include
using namespacestd;
voidFullPermutation(intarray[],intleft,intright)
{
if(left == right)
{
for(inti = 0;i
咦~ 递归写出的全排列有点不完美,它并不严格遵循字典序。
但是熟悉C++ 的朋友肯定知道另一种更简单,更完美的全排列方法。
全排列字典序全排列全排列递归的⽅法参考 leetcode 47字典序算法:升序实现:判断了是否相等计算全排列的数量⽅法为 n!/ (m!*p!*...) m,p为重复的数字的重复量#include<iostream>#include<algorithm>#include<vector>using namespace std;vector<int>nums;void Permutation(int len,vector<int>nums){int j, k;int flag=1; //start 0swhile (true){for(int i=0;i<len;i++){if(nums[i]==0&&flag)continue;else{flag=0;printf("%d",nums[i]);}}printf("");flag=1;for (j = len - 2; j >= 0 && nums[j] >= nums[j + 1]; j--);//注意此处 j >= 0 判断条件在前,加个等号即可if (j < 0) return;//结束for (k = len - 1; k > j&&nums[k] <= nums[j]; k--);//加个等号即可swap(nums[k], nums[j]);for (int l = j + 1, r = len - 1; l < r; l++, r--)swap(nums[l], nums[r]);}}int calc(int len){int summ=1;for(int i=1;i<=len;i++)summ*=i;return summ;}int main(){int n;while(cin>>n)nums.push_back(n);sort(nums.begin(),nums.end());int len=nums.size();//all 0int flag=0;for(int i=0;i<len;i++)if(nums[i]!=0){flag==1;break;}if(flag){cout<<"1 0"<<endl;return0;}vector<int>dup;int cnt=1;int bef=nums[0];for(int i=1;i<len;i++)if(bef==nums[i]){cnt++;continue;}else{dup.push_back(cnt);cnt=1;bef=nums[i];}//dup.push_back(cnt);vector<int>::iterator iter=dup.begin();int divide=1;for(iter;iter!=dup.end();iter++)divide*=calc(*iter);int summ=calc(len)/divide;printf("%d ",summ);Permutation(len,nums);system("pause");return0;}。
全排列递归算法概述及举例说明1. 引言1.1 概述在计算机科学中,全排列递归算法是一种常见且重要的算法。
它能够通过递归的方式生成给定元素集合的所有可能排列组合。
全排列递归算法的实现原理相对简单,但其应用领域十分广泛,并在许多其他算法中扮演着关键角色。
1.2 文章结构本文将首先介绍全排列递归算法的概述,包括其定义、特点和应用场景等。
随后,我们将深入探讨该算法的实现原理,并对其优缺点进行详尽分析。
接下来,我们会通过三个具体的举例说明来展示全排列递归算法的具体运用情况。
在最后部分,我们将探究该算法在其他领域中的应用以及进一步扩展与改进思路。
1.3 目的本文旨在提供一个清晰而全面的介绍全排列递归算法及其应用示例。
通过阅读本文,读者将能够了解该算法的基本原理、实现方法和优缺点,并对其在不同场景下的具体应用有更深入、更具体的认识。
此外,本文还将探讨该算法的拓展和改进思路,为读者提供继续研究和应用的思路。
2. 全排列递归算法概述2.1 什么是全排列递归算法全排列递归算法是一种用于确定给定元素集合所有可能排列方式的算法。
它通过递归的方式将原始集合分解成更小的子问题,并且在每个步骤中交换不同位置上的元素来生成新的排列。
这个过程会一直持续到达到基本情况,也就是无法再进一步交换元素位置为止。
2.2 实现原理全排列递归算法可以通过以下方法实现:1) 确定基本情况:当待排序集合只包含一个元素时,即达到了基本情况。
此时,我们可以认为该集合已经被排列好了。
2) 对于超过一个元素的集合,选择其中一个元素作为固定元素,并将其与其他每个位置上的元素进行交换。
这样,我们就得到了以不同元素开头的一系列子问题。
3) 对于每个子问题,重复步骤2中的操作,对其余部分进行递归地全排列。
4) 在重复进行步骤2和3后,我们可以得到最终的全排列结果。
2.3 优缺点分析全排列递归算法具有以下优点:- 算法逻辑简单易懂,易于实现和理解。
- 能够生成给定元素集合的所有可能排列方式。
java 常用算法总结-回复Java常用算法总结在Java程序开发中,算法是非常重要的一部分,它们能够解决各种问题,并为程序提供高效的解决方案。
本文将总结Java中常用的算法,并为每种算法的主题进行详细解释。
以下是本文的主要内容:1. 基础算法:涵盖了常见的算法思想和数据结构,例如递归、排序、查找等。
1.1 递归:递归是一种调用自身的算法。
它常用于解决可以被分解为规模较小的子问题的问题。
1.2 排序算法:排序算法用于对一组数据进行排序,常见的算法包括冒泡排序、插入排序、选择排序、快速排序、归并排序等。
1.3 查找算法:查找算法用于在一组数据中查找指定的元素,常见的算法包括线性查找、二分查找、哈希查找等。
2. 图算法:图算法用于解决与图相关的问题,例如找到两个节点之间的最短路径、判断图是否连通等。
2.1 广度优先搜索(BFS):BFS算法用于在图中寻找最短路径。
它从给定的起始节点开始,逐层遍历图中的节点,直到找到目标节点或遍历完所有节点。
2.2 深度优先搜索(DFS):DFS算法用于在图中寻找路径。
它从给定的起始节点开始,沿着一条路径一直遍历直到不能继续才回溯,继续遍历其他路径。
2.3 最小生成树(MST):最小生成树算法用于在给定的图中找到一棵包含所有节点的树,并使得树的所有边的权重之和最小。
2.4 拓扑排序:拓扑排序算法用于对有向无环图进行排序。
它将图中的节点按照依赖关系进行排序,使得每个依赖关系的节点都排在其依赖的节点之后。
3. 动态规划:动态规划是一种通过将问题分解为子问题并解决子问题来解决复杂问题的算法。
它通常用于解决最优化问题。
3.1 斐波那契数列:斐波那契数列是一个经典的动态规划问题,它的定义为f(n) = f(n-1) + f(n-2),其中f(0) = 0,f(1) = 1。
3.2 背包问题:背包问题是一个经典的动态规划问题,它的目标是在给定的背包容量下,将价值最大化。
常见的背包问题包括01背包问题、完全背包问题和多重背包问题。
全排列的⼏种实现(含字典序排列算法分析) 始于⼀个很简单的问题:⽣成{0,1,2,3,...,n-1}的n!种排列,即全排列问题。
下⾯介绍⼏种全排列的实现,以及探讨⼀下其解题思路。
基于枚举/递归的⽅法思路: 基于枚举的⽅法,也可以说是基于递归的⽅法,此⽅法的思路是先将全排列问题的约束进⾏放松,形成⼀个较容易解决的新问题,解新问题,再对新问题进⾏约束,解出当前问题。
以上全排列问题是⽣成{0,1,2,...,n-1}的n!个排列,隐含的⼀个约束是这个n个位置上的数必须是给出的集合中的数,不能重复使⽤。
当我们将此约束放松的时候,问题就变成了n个位置每个位置上有0~n-1种可能出现的数字,列出所有n n种数列,即在每⼀位上枚举所有的可能。
新问题的算法⾮常简单:private Integer[] perm;private void permut(int pos, int n) {if (pos == n) {for (int i = 0; i < perm.length; i++) {System.out.print(perm[i]);}System.out.println();return;}for (int i = 0; i < n; i++) {perm[pos] = i;permut(pos+1, n);}} ⽽我们实际的问题只要保证每⼀位上的数字在其他位置上没有使⽤过就⾏了。
private boolean[] used;private Integer[] perm;private void permut(int pos, int n) {if (pos == n) {for (int i = 0; i < perm.length; i++) {System.out.print(perm[i]);}System.out.println();return;} //针对perm的第pos个位置,究竟使⽤0~n-1中的哪⼀个进⾏循环for (int i = 0; i < n; i++) {if (used[i] == false) {perm[pos] = i;used[i] = true; //i已经被使⽤了,所以把标志位设置为Truepermut(pos+1, n);used[i] = false; //使⽤完之后要把标志复位}}} 或者完全按递归是思想,对{0,1,2,...,n-1}进⾏排列,分别将每个位置交换到最前⾯位,之后全排列剩下的位:private static void PermutationList(int fromIndex, int endIndex){if (fromIndex == endIndex)Output();else{for (int index = fromIndex; index <= endIndex; ++index){// 此处排序主要是为了⽣成字典序全排列,否则递归会打乱字典序Sort(fromIndex, endIndex);Swap(fromIndex, index);PermutationList(fromIndex + 1, endIndex);Swap(fromIndex, index);}}}基于字典序的⽅法 基于字典序的⽅法,⽣成给定全排列的下⼀个排列,所谓⼀个的下⼀个就是这⼀个与下⼀个之间没有其他的。
两种常⽤的全排列算法(java)问题:给出⼀个字符串,输出所有可能的排列。
全排列有多种算法,此处仅介绍常⽤的两种:字典序法和递归法。
1、字典序法:如何计算字符串的下⼀个排列了?来考虑"926520"这个字符串,我们从后向前找第⼀双相邻的递增数字,"20"、"52"都是⾮递增的,"26 "即满⾜要求,称前⼀个数字2为替换数,替换数的下标称为替换点,再从后⾯找⼀个⽐替换数⼤的最⼩数(这个数必然存在),0、2都不⾏,5可以,将5和2交换得到"956220",然后再将替换点后的字符串"6220"颠倒即得到"950226"。
算法概括:从后向前遍历,找出第⼀个交换点,再按照规则找出第⼆个交换点,将两者进⾏交换,对第⼀个交换点之后的字符进⾏颠倒操作package algorithm;import java.util.Arrays;public class DictionaryPermutation {private char[] data;private int length;public void permutate(String input) {// change the data type to we neededchangeToData(input);// sort the data from small to bigArrays.sort(data);// output all the orderSystem.out.println(data);while (nextPermutate()) {System.out.println(data);}}private void changeToData(String input) {if (input == null)return;data = input.toCharArray();length = data.length;}private boolean nextPermutate() {int end = length - 1;int swapPoint1 = end, swapPoint2 = end;// the actual swap-point is swapPoint1 - 1while (swapPoint1 > 0 && data[swapPoint1] <= data[swapPoint1 - 1])swapPoint1--;if (swapPoint1 == 0)return false;else {while (swapPoint2 > 0 && data[swapPoint2] <= data[swapPoint1 - 1])swapPoint2--;swap(data, swapPoint1 - 1, swapPoint2);reverse(data, swapPoint1, end);return true;}}private void swap(char[] data, int left, int right) {char temp = data[left];data[left] = data[right];data[right] = temp;}private void reverse(char[] data, int left, int right) {for (int i = left, j = right; i < j; i++, j--)swap(data, i, j);}public static void main(String... args) {DictionaryPermutation p = new DictionaryPermutation();p.permutate("aab");}}2、递归法为⽅便起见,⽤123来⽰例下。
字典排序算法实现全排列相关资料免积分下载:字典排序算法实现全排列的步骤:总结:1.从右向左找,找到第⼀个⽐下⼀个元素还⼩的地⽅,记下位置,标注为左元素。
2.从右向左找,找到第⼀个⽐左元素⼤的元素,记下位置,标注为右元素。
3.交换左元素和右元素。
4.不管现在左元素位置上放的是谁,将左元素右边的序列逆序。
5.这样就得到了⼀个新数了。
6.可以继续重复1-5,来继续得到下⼀个排列。
7.如果再也找不到⼀个⽐下⼀个元素还⼩的地⽅,那么意味着这个序列已经降序了,排列完成了,那就结束吧。
代码如下:<?php/*** 打印数组** @param int $num 数组内的元素个数*/function printArr($num){global$array;//全局数组for($i=0;$i<$num;$i++)echo$array[$i];echo "<br>";}/*** 交换值** @param string $a* @param string $b*/function swap(&$a,&$b){$temp= $a;$a = $b;$b = $temp;}/*** 将第$m个和$n个之间的数据倒置排序** @param int $m 数组中的位序$m* @param int $n 数组中的位序$n*/function convert($m,$n){global$array;//全局数组for ($i=$m,$j=$n;$j>$i;$i++,$j--)swap($array[$i],$array[$j]);}/*** 对1~n进⾏全排列** @param int $num 元素的总个数* @return 1*/function dictionary_sort($num){global$array;//全局数组if ($num==1){echo "1<br>";return 1;}while (1){printArr($num); //打印数组for ($i=$num-2;$i>=0;$i--){ //步骤1:从后向前找,找到第⼀个⽐下⼀个元素还⼩的地⽅,记下位置,标注$iif ($array[$i]<$array[$i+1])break;//得到$iif ($i==0)return 1; //函数出⼝}for ($j=$num-1;$j>$i;$j--){ //步骤2:从后向前找,找到第⼀个⽐$i元素⼤的元素,记下位置,标注为$jif ($array[$j]>$array[$i])break;}swap($array[$i],$array[$j]);//步骤3:交换$array[$i]和$array[$j]的数据convert($i+1,$num-1); //步骤4: 将$i个元素右边的序列逆序}}$array=array();$num=5;for ($i=0;$i<$num;$i++){$array[$i]=$i+1;}dictionary_sort($num);原创⽂章:转载请注明出处:。
全排列问题是一种经典的算法问题,它要求对一组元素进行排列,得到所有可能的排列方式。
全排列问题可以使用递归算法进行求解。
递归算法的基本思路是将原问题分解为若干个子问题,然后求解这些子问题,最后将子问题的解组合起来得到原问题的解。
对于全排列问题,可以将其分解为两个子问题:
1.考虑第一个元素在排列中的位置,将其与后面的元素进行全排列。
2.不考虑第一个元素在排列中的位置,对后面的元素进行全排列。
3.通过递归地求解这两个子问题,可以得到所有可能的排列方式。
具体实现过程如下:
1.定义一个递归函数permute,它接受一个整数n和一个整数数组arr作为参
数。
n表示要排列的元素个数,arr表示要排列的元素。
2.如果n等于0,说明已经排列完了所有的元素,此时直接返回空数组。
3.如果n等于1`,说明只有一个元素需要排列,此时直接返回包含这个元素的
数组。
4.否则,将arr数组分成两部分:第一个元素和后面的元素。
递归地求解以下
两个子问题:
a. 考虑第一个元素在排列中的位置,将其与后面的元素进行全排列。
b. 不考虑第一个元素在排列中的位置,对后面的元素进行全排列。
5.将两个子问题的解组合起来,得到原问题的解。
6.返回原问题的解。
这个算法的时间复杂度是指数级的,因为对于每一个排列方式,它需要递归地求解两个子问题。
因此,当元素个数较大时,这个算法可能会非常耗时。
本文由我司收集整编,推荐下载,如有疑问,请与我司联系实现全排列的两种算法:字典序列法以及递归算法(java)2014/10/19 0 一.全排列之字典序列法
/** * 这是一个实现全排列的字典序列算法,可适用于有数据重复以及无数据重复
的字符串----注意:字符要先从小到大排序* 算法描述:例如:645321 的下一个数:
* 1.左边的数要大于右边:从最右- 最左,遍历查询是否有邻近左边的数小于右边的
数,有就停止遍历,本例:4 5. * 2.把找到的左边那个数,与其右边的所有数比较,从
右向左逐一比较,找到第一个比它大的,然后交换。
本例:比4 大的右边第一个数
是5. * 3.将两个数对换,则字符可分为65,4321,把4321 从小到大排序:1234* 4.
下一个字符序列是:651234. span > * * @param ary //要排列的数组*/public static void dictorySerial(int[] ary1) {Arrays.sort(ary1);System.out.println( 1: + Arrays.toString(ary1));int i = 2;while (true) {int j;for (j = ary1.length - 1; j j--) {if (ary1[j - 1] ary1[j]) {for (int k = ary1.length - 1; k j - 1; k--) {if (ary1[k] ary1[j - 1]) {int temp =
ary1[j - 1];ary1[j - 1] = ary1[k];ary1[k] = temp;break;}}int[] ary2 = new int[ary1.length - j];System.arraycopy(ary1, j, ary2, 0,
ary2.length);Arrays.sort(ary2);System.arraycopy(ary2, 0, ary1, j, ary2.length);System.out.println((i++) + : + Arrays.toString(ary1));break;}}if (j == 0) {break;}}}二.全排列之递归算法
/** * 这是关于java 全排列的递归算法,本算法不适用于字符串中有重复数字。
-
--注意:交换两个数后,后面要在交换过来,不要影响要排列的字符序列(*)*
算法过程:如:123 的全排列:* 1.可以看成:以1 开头的全排列,以2 开头的全
排列,以3 开头的全排列/span 表示成1(23),2(13),3(12)的全排列,即23 全排列,13
全排列,12 全排列. span > span > span > span > span > span > span > span > span > span
> span > span > span >public static void recurrence(int[] ary2, int start, int end) {if (start == end) {System.out.println((++i) + : + Arrays.toString(ary2));} else {for (int i = start; i = end; i++) {swap(ary2, start, i);recurrence(ary2, start + 1, end);swap(ary2, start, i);System.out.println(Arrays.toString(ary2));}}}public static void swap(int[] ary2, int start,。