字符串全排列的题目,还是套用模板,同样要注意ret的size问题会变化。而且与上一题不同的是不光是要在ret后面添加进新的组合,而且还要移除前面用过的组合。类似一个队列。
另外Java的substring中区间闭合情况是左闭右开 [ ) 所以想把一个字符串拆成两个区间就可以用这一句:
for(int j=0; j<=tmp.length(); j++){
// substring区间: [)
ret.add(tmp.substring(0, j) + head + tmp.substring(j));
}
思路还是按照这里写的:http://hawstein.com/posts/8.4.html
思路一:
我们可以把串“abc”中的第0个字符a取出来,然后递归调用permu计算剩余的串“bc” 的排列,得到{bc, cb}。然后再将字符a插入这两个串中的任何一个空位(插空法), 得到最终所有的排列。比如,a插入串bc的所有(3个)空位,得到{abc,bac,bca}。 递归的终止条件是什么呢?当一个串为空,就无法再取出其中的第0个字符了, 所以此时返回一个空的排列。
思路二:
我们还可以用另一种思路来递归解这个问题。还是针对串“abc”, 我依次取出这个串中的每个字符,然后调用permu去计算剩余串的排列。 然后只需要把取出的字符加到剩余串排列的每个字符前即可。对于这个例子, 程序先取出a,然后计算剩余串的排列得到{bc,cb},然后把a加到它们的前面,得到 {abc,acb};接着取出b,计算剩余串的排列得到{ac,ca},然后把b加到它们前面, 得到{bac,bca};后面的同理。最后就可以得到“abc”的全序列。
package Recursion;
import java.util.ArrayList;
/**
* Write a method to compute all permutations of a string
*
* 写一个函数返回一个串的所有排列
*
*/
public class S9_5 {
public static void main(String[] args) {
ArrayList<String> list = getPerms("abc");
System.out.println("There are " + list.size() + " permutations.");
for (String s : list) {
System.out.println(s);
}
}
// ========================================= 方法一
/*
* ABC:
*
* A -> [BC]:
* ABC, BAC, BCA
*
* A -> [CB]
* ACB, CAB, CBA
*/
public static ArrayList<String> getPerms(String str) {
ArrayList<String> ret = new ArrayList<String>();
rec(str, 0, ret);
return ret;
}
public static void rec(String str, int start, ArrayList<String> ret){
if(start == str.length()){
ret.add(""); // Basecase总是要插入一个空字符串
return;
}
rec(str, start+1, ret); // 处理子问题
int size = ret.size(); // 还是因为ret长度会变化所以记录在size变量中
String head = str.substring(start, start+1);
for(int i=0; i<size; i++){
String tmp = ret.get(0); // 从ArrayList头取出,并删除
ret.remove(0);
for(int j=0; j<=tmp.length(); j++){ // 加到ArrayList后头
// substring区间: [)
ret.add(tmp.substring(0, j) + head + tmp.substring(j));
}
}
}
//================================= 另一种方法二
public static ArrayList<String> getPerms2(String str){
ArrayList<String> ret = new ArrayList<String>();
rec2("", str, ret);
return ret;
}
/*
* ABC:
*
* (A,BC)
* (AB,C)
* (ABC,)
* (AC,B)
* (ACB,)
*
* (B,AC)
* (BA,C)
* (BAC,)
* (BC,A)
* (BAC,)
*
* (C,AB)
* (CA,B)
* (CAB,)
* (CB,A)
* (CBA,)
*
*/
// done: 已经完成部分,rest:尚未完成部分
public static void rec2(String done, String rest, ArrayList<String> ret){
if(rest.length() == 0){
ret.add(new String(done));
return;
}
// 遍历rest的所有字符,每次选择一种结合到done,rest去掉被选择的那个字符
for(int i=0; i<rest.length(); i++){
rec2(done+rest.charAt(i), rest.substring(0, i)+rest.substring(i+1), ret);
}
}
}
针对第二种方法,再补充一种用StringBuilder的方法,因为StringBuilder可以很方便地对字符串修改,特别记住以下StringBuilder函数:
public StringBuilder insert(int offset, char c)
public StringBuilder deleteCharAt(int index)
public StringBuilder append(char c)
public static void main(String []args){
String s = "abcdefg";
rec(new StringBuilder(), new StringBuilder(s));
}
public static void rec(StringBuilder done, StringBuilder rest){
if(rest.length() == 0) {
System.out.println(done.toString());
return;
}
for(int i=0; i<rest.length(); i++) {
char c = rest.charAt(i);
done.append(c);
rest.deleteCharAt(i);
rec(done, rest);
rest.insert(i, c);
done.deleteCharAt(done.length()-1);
}
}
PS1:Generate all the strings of n bits, Assume A[0...n-1] is an array of size n.
public class HelloWorld{
public static void main(String []args){
bin(3);
}
static char[] ss = {0,0,0};
public static void bin(int len){
if(len == 0) {
System.out.println(new String(ss));
return;
}
ss[len-1] = '0';
bin(len-1);
ss[len-1] = '1';
bin(len-1);
}
}
得出结果:
000 100 010 110 001 101 011 111
PS2: Generate all the string of length n drawn from 0...k-1
public class HelloWorld{
public static void main(String []args){
int len = 3;
// bin(len);
k_bin(len, 5);
}
static char[] ss = {0,0,0};
public static void bin(int len){
if(len == 0) {
System.out.println(new String(ss));
return;
}
ss[len-1] = '0';
bin(len-1);
ss[len-1] = '1';
bin(len-1);
}
public static void k_bin(int len, int k) {
if(len == 0) {
System.out.println(new String(ss));
return;
}
for(int i=0; i<k; i++) {
ss[len-1] = (char)(i+'0');
k_bin(len-1, k);
}
}
}
000 100 200 300 400 010 110 210 310 410 020 120 220 320 420 030 130 230 330 430 040 140 240 340 440 001 101 201 301 401 011 111 211 311 411 021 121 221 321 421 031 131 231 331 431 041 141 241 341 441 002 102 202 302 402 012 112 212 312 412 022 122 222 322 422 032 132 232 332 432 042 142 242 342 442 003 103 203 303 403 013 113 213 313 413 023 123 223 323 423 033 133 233 333 433 043 143 243 343 443 004 104 204 304 404 014 114 214 314 414 024 124 224 324 424 034 134 234 334 434 044 144 244 344 444