前例中,我们求了一个字符串的排列组合,其中再细分出一种情况,长度与原字符串长度相同的排列组合。

这里,我们只求组合,不要求“排列”。从数学的解集上看,本例的解集是上一例的子集。思路有所不同。

具体的方法是,先自己求简单的,比如abcde中长度为2的子串组合,然后用笔记录下自己输出的过程。发现如下:

1、问题可以化解为求某个字符串长度的K(K<=n)的子串组合,当K从1到n时,解集的集合即为所求

2、求某个字符串长度的K(K<=n)的子串组合,模拟人脑的思路是:比如求abcde中长度为3的子串组合:

    有三大类,分别是a,b,c开头,而且c开头正好是cde一种组合,d开头的没有啦。

    然后a开头的又可以化解为求“bcde”中长度为2的子串组合,发现可以递归。

    于是用笔,画出每个思路的路线图,归纳总结,可得出代码。虽然说是这么简单,但是我想了一整天,脑袋真是笨。中途还在想,自己是不是没有写代码的天赋呢?一度绝望中。

    但是后来上厕所,想想,也许吧,不算聪明,跟google那帮人绝对没法比,但是世界不仅需要决定聪明的人,也需要我们这一类平庸之辈啊,想想,还是自己开心就好,开心的时候,就是自己解答出来的时刻,感觉真好。

    如厕悟出的一个道理是,写程序,一定要严谨,像数学题一样,来不得一点马虎,否则就是南辕北辙,缘木求鱼。集中精力,很重要,特别是像我这种非绝顶聪明的人,一定不能天马行空,要踏踏实实,一步一步地把思路写出来,越清晰越靠谱,来不得一点儿天马行空。也许就是这一点点的差别,导致自己竟然耗费了一整天的时间,才在最后的时候,静下心来,瞬间解决出来了。感慨万千,一定要心静,才行!!!

     人笨一点,没关系,郭靖还能练成“降龙十八掌”呢,郭靖比黄蓉更快学会“双手互博术”,更是一例。不放弃,坚持!

    

/**
* 输入一个字符串,输出该字符串中字符的所有组合。
* 举个例子,如果输入abc,它的组合有a、b、c、ab、ac、bc、abc。
*/
public class StringCombination {

private int len;

public void setLen(int i) {
this.len=i;
}

/**
* 求以start开头的,长度为wanted的子串
*
@param k:字符串数组
*
@param start:数组小标
*
@param wanted:所需子串的长度
*
@param pre:前缀
*/
public void getStringCombination(char[] k,int start,int wanted,String pre) {
if(wanted==0) {
System.out.println(pre);
return;
}

int last_index=len-wanted;
for(int i=start;i<=last_index;i++) {
// System.out.print(k[i]);
getStringCombination(k, i+1, wanted-1,pre+k[i]);
// System.out.println("");
}

}

public void getRs(String content) {
//组合子串的长度从1到length
for(int i=1;i<=content.length();i++) {
getStringCombination(content.toCharArray(), 0, i,"");
}
}

public static void main(String[] args) {
StringCombination sCombination=new StringCombination();
Scanner scanner=new Scanner(System.in);
System.out.println("please input :");
String content=scanner.nextLine();
sCombination.setLen(content.length());
sCombination.getRs(content);
}

}
posted @ 2011-12-04 17:37 hello_caesar 阅读(159) 评论(0) 编辑

【原题】比如,输入abc,输出abc、acd、bac、bca、cab、cba。

主要的思路:

1、递归,每个字符在每个位置都出现(暂时没有处理重复的字符)

2、在最后的字符组合长度为字符串长度时输出

 1 package com.persia.test;
2
3 import java.util.Scanner;
4
5 public class StringArrangement {
6
7 private int len;
8
9 private char[] getRest(char[] arr,int i) {
10 char[] rs=new char[arr.length-1];
11 for(int j=0;j<i;j++) {
12 rs[j]=arr[j];
13 }
14 for(int j=i+1;j<arr.length;j++) {
15 rs[j-1]=arr[j];
16 }
17 return rs;
18 }
19 private void arrangeString(String pre,char[] arr) {
20 //System.out.println("pre:"+pre);
21 if(pre.length()==len) {
22 System.out.println(pre);
23 }
24 if(arr.length<1)
25 return;
26
27 //System.out.print(pre);
28 for(int i=0;i<arr.length;i++) {
29 char first=arr[i];
30 //System.out.print(first);
31 char[] rest=getRest(arr, i);
32 arrangeString(pre+first,rest);
33 }
34 //System.out.println("");
35 }
36
37 public void getResult(String content) {
38 char[] arr=content.toCharArray();
39 len=arr.length;
40 arrangeString("",arr);
41
42 }
43
44
45 public static void main(String[] args) {
46 Scanner scanner=new Scanner(System.in);
47 System.out.println("please input:\n");
48 String content=scanner.nextLine();
49 StringArrangement sArrangement=new StringArrangement();
50
51 sArrangement.getResult(content);
52
53 }
54
55 }

 

比如输入abcd,输出:

abcd abdc acbd acdb adbc adcb
bacd badc bcad bcda bdac bdca
cabd cadb cbad cbda cdab cdba

dabc dacb dbac dbca dcab dcba

 

【改进】由于每次都需要新的数组来存放剩下的字符,比较浪费空间。改为利用原有的空间,将首位字符与最后一位调换,递归时告诉其长度即可。

private void swap(char[] arr,int i,int j) {
if(i==j)
return;
char tmp=arr[i];
arr[i]=arr[j];
arr[j]=tmp;
}
private void arrangeString(String pre,char[] arr,int length) {
//System.out.println("pre:"+pre);
if(pre.length()==len) {
System.out.println(pre);
}
if(length<1)
return;

//System.out.print(pre);
for(int i=0;i<length;i++) {
char first=arr[i];
//System.out.print(first);
swap(arr, i, length-1);
arrangeString(pre+first,arr,length-1);
swap(arr, length-1,i);
}
//System.out.println("");
}

public void getResult(String content) {
char[] arr=content.toCharArray();
len=arr.length;
arrangeString("",arr,arr.length);

}

由于前面置换了位置,在进行下一个遍历前,要置换回来。

 

【变体1】输入一个字符串,输出该字符串中字符的所有排列组合。如输入ab,排列组合有a、b、ab、ba。

将上面的代码稍微改下即可:将判断长度输出去掉,每次都输出。

   private void arrangeString(String pre,char[] arr,int length) {
//System.out.println("pre:"+pre);
//if(pre.length()==len) {
System.out.println(pre);
//}
if(length<1)
return;

//System.out.print(pre);
for(int i=0;i<length;i++) {
char first=arr[i];
//System.out.print(first);
swap(arr, i, length-1);
arrangeString(pre+first,arr,length-1);
swap(arr, length-1,i);
}
//System.out.println("");
}



【变体2】输入一个字符串,输出该字符串中字符的所有组合。举个例子,如果输入abc,它的组合有a、b、c、ab、ac、bc、abc。

 



posted @ 2011-12-02 23:18 hello_caesar 阅读(174) 评论(0) 编辑