字符串的排列和组合问题

1、字符串的全排列

题目:{a,b,c}要求输出{abc,acb,bac,bca,cab,cba}。

字符串全排列可以把字符串看成两个部分,第一个部分为它的一个字符,第二部分是后面的字符。

分两步完成:首先求所有可能出现在第一个位置的字符,即把第一个字符与后面的所有字符交换。第二步固定第一个字符,求后面所有字符的排列。从中可以看出是典型的递归思路。

 1     public void helper(char[] array, int cur){
 2         if ( cur == array.length - 1 ) print(array);
 3         else {
 4             for ( int i = cur ; i < array.length ; i ++ ){
 5                 swap(array,cur,i);
 6                 helper(array,cur+1);  //固定第一个字符,对后面所有字符全排列
 7                 swap(array,i,cur);
 8             }
 9         }
10     }

如果给的字符中出现重复,即{a,b,c,c}这种情况,可以判断当前准备交换的字符,如果当前准备交换的字符已经在cur前面的字符中出现过了,就跳过,否则就交换。修改后方法如下:

 1     public void helper(char[] array, int cur){
 2         if ( cur == array.length - 1 ) print(array);
 3         else {
 4             for ( int i = cur ; i < array.length ; i ++ ) {
 5                 if (!isExit(array, cur, i)) {
 6                     swap(array, cur, i);
 7                     helper(array, cur + 1);  //固定第一个字符,对后面所有字符全排列
 8                     swap(array, i, cur);
 9                 }
10             }
11         }
12     }
13     private boolean isExit(char[] array, int cur, int i) {
14         for ( int k = cur ; k < i ; k ++ ){
15             if ( array[k] == array[i] ) return true;
16         }
17         return false
18     }

2、字符串组合

题目:{a,b,c}要求输出{a,b,c,ab,ac,bc,abc}。

分析,可以将题目分成小问题来理解,1个字符的组合+2个字符的组合+3个字符的组合,因此我们只要找到一般的方法,即从n个字符中找m个字符的组合就可以了。

我们可以把n个字符分成两部分,第一个字符和其他所有字符。如果组合里包含第一个字符,则下一步在剩余的字符里选取m-1个字符;如果组合里不包含第一个字符,则下一步在剩余的n-1个字符里选取m个字符,从中可以看出又是个递归的过程。

 1     Stack<Character> stack = new Stack<>();
 2     public void helper(char[] array){
 3         for ( int i = 1 ; i <= array.length ; i ++ )
 4             combination(array,0,i);
 5     }
 6     private void combination(char[] strArr, int begin, int num) {
 7         if (num == 0) {
 8             System.out.println(stack);
 9             return;
10         }
11         if (begin >= strArr.length) {
12             return;
13         } else {
14             //把第一个字符放入组合中,在剩余的字符中选取num-1个字符
15             stack.push(strArr[begin]);
16             combination(strArr, begin + 1, num - 1);
17             //组合里不包含第一个字符,则下一步在剩余的字符中选取num个字符
18             stack.pop();
19             combination(strArr, begin + 1, num);
20         }
21     }

helper函数表示求长度为i的全排列。

还有一种更nb的方法,因为组合问题,比如3个元素的组合就有2^3-1种,所以不妨给他们进行编号,就像上面的问题,从a——abc一次编号为 001——111。1就代表该位置出现字符。例如:001->c,010->b,101->ac......,所以原题就是要求输出"001"-"111"这2^n-1个组合对应的字符串。

 1 public static void main(String[] args) {
 2
 3   String s = "abc";
 4   ArrayList<String> result = combineString(s);
 5   for(String r : result){
 6     System.out.println(r);
 7   }
 8 }
 9
10 private static ArrayList<String> combineString(String s) {
11   int len = s.length();
12   ArrayList<String> list = new ArrayList<String>();
13   int count = (int) (Math.pow(2, len));
14   for(int i = 1; i < count; ++i){
15     String temp = "";
16     String str = Integer.toBinaryString(i);
17     while(str.length() < len){
18       str = "0" + str;
19     }
20     for(int j = 0; j < str.length(); ++j){
21       if(str.charAt(j) == ‘1‘){
22         temp += s.charAt(j);
23       }
24     }
25     list.add(temp);
26   }
27   return list;
28 }

原文地址:https://www.cnblogs.com/boris1221/p/9388209.html

时间: 2024-11-10 14:37:42

字符串的排列和组合问题的相关文章

[笔试题]字符串的排列和组合

[代码] C++ Code 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411

字符串的排列组合总结

问题1 :输入一个字符串,打印出该字符串中字符的所有排列.例如输入字符串abc,则输出由字符a.b.c所能排列出来的所有字符串abc.acb.bac.bca.cab和cba. 思路:这是个递归求解的问题.递归算法有四个特性:(1)必须有可达到的终止条件,否则程序将陷入死循环:(2)子问题在规模上比原问题小:(3)子问题可通过再次递归调用求解:(4)子问题的解应能组合成整个问题的解. 对于字符串的排列问题.如果能生成n - 1个元素的全排列,就能生成n个元素的全排列.对于只有1个元素的集合,可以直

字符串数组元素排列与组合的Java递归实现

排列与组合的Java递归实现 (参考) 我们在笔试面试过程中经常会遇到关于排列与组合的问题,其实这些可以通过递归简单的实现,看下面两个例子: (1)关于字符串排列的问题 输入一个字符串,打印出该字符串中字符的所有排列.例如输入字符串abc,则输出由字符a.b.c所能排列出来的所有字符串abc.acb.bac.bca.cab和cba. 可以这样想:固定第一个字符a,求后面两个字符bc的排列.当两个字符bc的排列求好之后,我们把第一个字符a和后面的b交换,得到bac,接着我们固定第一个字符b,求后面

【编程题目】字符串的排列(字符串)★

53.字符串的排列(字符串).题目:输入一个字符串,打印出该字符串中字符的所有排列.例如输入字符串 abc,则输出由字符 a.b.c 所能排列出来的所有字符串abc.acb.bac.bca.cab 和 cba. 这道题花了我一天,要好好总结! 思路:这道题目感觉有些难,主要是字符串中的字符可能会有重复.我的想法是把一共有多少种字符和每种字符出现的次数统计出来,每个位置对这些字符变量,下一个位置的可用字符减小,再遍历. /* 53.字符串的排列(字符串). 题目:输入一个字符串,打印出该字符串中字

经典算法学习之分治法(以排列、组合程序为例)

分治法的思想:将原问题分解为几个规模较小但类似于原问题的子问题,递归的求解这些子问题,然后再合并这些子问题的解来建立原问题的解. 分治法在每层递归是遵循的三个步骤: (1)分解原问题为若干个子问题,这些子问题是原问题的规模较小的实例. (2)解决这些子问题,队规的求解各个子问题,当子问题规模足够小的时候,直接求解. (3)合并这些子问题的解构成原问题的解. 显然归并排序是一个非常经典规矩的分治法的例子,鉴于之前已经写过一篇关于归并排序的博文,这里不在使用归并排序作为例子. 注意分治法的每一层递归

字符串的全排列与组合

一.字符串的排列 问题描述:给出一个字符串,请设计一个函数输出所有可能的排列,如abc,可能的排列顺序有abc.acb.bac.bca.cba.cab  问题分析:要对长度为n的序列进行排序,可以转化为固定第一个的值,再对剩余的n-1个进行排序的问题,可以用递归实现.由于第一个的值可以是任何一个,可用第一个值与其他值依次交换实现.如序列abc可以转化为如下三种情况: (1)第一个固定为a,对bc进行排序 (2)第一个固定为b,对ac进行排序 (3)第一个固定为c,对ab进行排序 代码: 二.字符

28 - 字符串的全排列和组合

字符串的排列 题目描述:http://ac.jobdu.com/problem.php?pid=1369 输入一个字符串,按字典序打印出该字符串中字符的所有排列.例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba. 分两步: 第一步:求所有可能出现在第一个位置的字符,即把第一个字符和后面所有的字符都交换一次: 第二步:固定第一个位置的字符,求后面所有字符的排列. 终止条件:当要求固定位置的字符为'\0'时,说明已经排列到字符串尾.

java中关于排列和组合的有关算法

收集的排列加组合的各种算法,还有待完善: 一.利用二进制状态法求排列组合,此种方法比较容易懂,但是运行效率不高,小数据排列组合可以使用 import java.util.Arrays; //利用二进制算法进行全排列 //count1:170187 //count2:291656 public class test { public static void main(String[] args) { long start=System.currentTimeMillis(); count2();

算法 输出字符串字符的任意组合

编程列出一个字符串的全字符组合情况,原始字符串中没有重复字符,例如: 原始字符串是"abc",打印得到下列所有组合情况: "a" "b" "c" "ab" "bc" "ca" "ba" "cb" "ac" "abc" "acb" "bac" &quo