1. 题目描述
输入一个字符串,按字典序打印出该字符串中字符的所有排列。
2. 示例
例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。
输入一个字符串,长度不超过9(可能有字符重复),字符只包括大小写字母。
3. 解题思路
使用递归法,问题转换为先固定第一个字符,求剩余字符的排列;求剩余字符排列时跟原问题一样。
递归算法实现:
image
(1) 遍历出所有可能出现在第一个位置的字符(即:依次将第一个字符同后面所有字符交换);
(2) 固定第一个字符,求后面字符的排列(即:在第1步的遍历过程中,插入递归进行实现)。
以"abc"为例
1.第一次进到这里是ch=['a','b','c'],list=[],i=0,我称为 状态A ,即初始状态
那么j=0,swap(ch,0,0),就是['a','b','c'],进入递归,自己调自己,只是i为1,交换(0,0)位置之后的状态我称为 状态B
i不等于2,来到这里,j=1,执行第一个swap(ch,1,1),这个状态我称为 状态C1 ,再进入递归函数,此时标记为T1,i为2,那么这时就进入上一个if,将"abc"放进list中
-------》此时结果集为["abc"]
2.执行完list.add之后,遇到return,回退到T1处,接下来执行第二个swap(ch,1,1),状态C1又恢复为状态B
恢复完之后,继续执行for循环,此时j=2,那么swap(ch,1,2),得到"acb",这个状态我称为C2,然后执行递归函数,此时标记为T2,发现i+1=2,所以也被添加进结果集,此时return回退到T2处往下执行
-------》此时结果集为["abc","acb"]
然后执行第二个swap(ch,1,2),状态C2回归状态B,然后状态B的for循环退出回到状态A
// a|b|c(状态A)
// |
// |swap(0,0)
// |
// a|b|c(状态B)
// / \
// swap(1,1)/ \swap(1,2) (状态C1和状态C2)
// / \
// a|b|c a|c|b
3.回到状态A之后,继续for循环,j=1,即swap(ch,0,1),即"bac",这个状态可以再次叫做状态A,下面的步骤同上
-------》此时结果集为["abc","acb","bac","bca"]
// a|b|c(状态A)
// |
// |swap(0,1)
// |
// b|a|c(状态B)
// / \
// swap(1,1)/ \swap(1,2) (状态C1和状态C2)
// / \
// b|a|c b|c|a
4.再继续for循环,j=2,即swap(ch,0,2),即"cab",这个状态可以再次叫做状态A,下面的步骤同上
-------》此时结果集为["abc","acb","bac","bca","cab","cba"]
// a|b|c(状态A)
// |
// |swap(0,2)
// |
// c|b|a(状态B)
// / \
// swap(1,1)/ \swap(1,2) (状态C1和状态C2)
// / \
// c|b|a c|a|b
5.最后退出for循环,结束。
4. Java实现
import java.util.ArrayList;
import java.util.List;
import java.util.Collections;
public class Solution {
public ArrayList Permutation(String str) {
List list = new ArrayList();
if (str.length() == 0) return (ArrayList)list;
permutationHelper(str.toCharArray(), 0, list); // 递归实现
Collections.sort(list);
return (ArrayList)list;
}
private void permutationHelper(char[] cs, int i, List list){
if (i == cs.length-1){ // 如果索引是最后一位的话
String s = String.valueOf(cs);
if (!list.contains(s)){ // 防止有重复的字符串,如输入为 aab时
list.add(s);
return;
}
}else{
for (int j = i; j < cs.length; j++){
swap(cs, i, j);
permutationHelper(cs, i+1, list);
swap(cs, i, j); // 回溯法,恢复之前字符串顺序,达到第一位依次跟其他位交换的目的
}
}
}
private void swap(char[] cs, int i, int j){ // 交换两个字符
char temp;
temp = cs[i];
cs[i] = cs[j];
cs[j] = temp;
}
}
5. Python实现
# -*- coding:utf-8 -*-
class Solution:
def Permutation(self, ss):
# write code here
if not ss:
return []
if len(ss) == 1:
return ss
ssList = list(ss)
ssList.sort() #将 字符串转换成列表并排序
ret = []
for i in range(len(ssList)): #依次取出一个字符,其余字符进行递归操作
if i > 0 and ssList[i] == ssList[i-1]: #如果存在字符相同的情况
continue
temp = self.Permutation(''.join(ssList[: i]) + ''.join(ssList[i+1: ]))
for j in temp:
ret.append(ssList[i] + j)
return ret
如果您觉得本文有用,请点个“赞”
image.png
本文介绍了如何使用Java和Python解决字符串排列问题。通过递归算法,分别展示了两种语言如何找出输入字符串的所有字典序排列。对于Java,利用了回溯法;Python则通过去除重复字符并递归生成排列。
1251

被折叠的 条评论
为什么被折叠?



