title: 2019-8-24 字符串的排列
tags: 算法,每日一题,字符串
字符串的排列
1. 题目描述
输入一个字符串,按字典序打印出该字符串中字符的所有排列,输入一个字符串,长度不超过9(可能有字符重复),字符只包括大小写字母。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。
2.题目解析
首先对于给定的一个字符串比如abc,对于第一个位置我们可以有三种选择,a,b,c。所以只需要每次都把字符串对应的字符换到第一个位置即可。比如现在我们把b换到了第一个位置bac
,那么这个时候相当于固定了第一个位置的字符了,对于后面的字符的处理就和之前的一样了(ok构成了递归了)。因此只要递归下去就可以解决问题了。但是这是没有考虑字符串中有重复元素的情况。
对于字符串中包含重复字符的情况,我们可能会尝试如果要交换的字符相同的我们就不交换,但是对于abb
,第一次aa交换不变,第二次ab交换得到bab
,第三次bba
。显然第三次的递归会得到一个bba
的结果,第二次的bab
也会得到一个bba
的结果。所以这种尝试是无效的。现在尝试策略二:在当前这次递归中,如果从from到当前交换的位置之间都没有相同的元素(保证之前没有出现固定当前元素的情况)。
这两个问题解决之后还有一个问题就是按照字典序输出,这需要在每次进行下一次递归之前对从from到to之间的元素进行一次字典排序即可。
2.1 思路解析
1、只考虑全排列的情况
2、考虑用重复的情况
错误的方式,相同的字符不交换
正确的情况:从交换位置处i
到from
之间如果有和i相同的字符就不交换也不会递归下去
3、需要字典排序的字符串全排列
class Solution {
public:
vector<string> Permutation(string str) {
vector<string> res;
if(str.empty()) return res;
sort(str.begin(), str.end());
permutation_recru(str, 0, str.size()-1, res);
return res;
}
void permutation_recru(string& str,int from, int to, vector<string>& res){
if(from == to) {
res.push_back(str);
return;
}
for(int i=from; i<=to; ++i){
sort(str.begin() + from, str.end());//这个只能放在这个位置
if(isSwap(str, from, i)){
swap(str, from, i);
permutation_recru(str, from+1, to, res);
swap(str, from, i);
}
}
}
void swap(string& str, int a, int b){
char temp = str[a];
str[a] = str[b];
str[b] = temp;
}
bool isSwap(string& str, int from, int to){
for(int i=from; i<to; ++i){
if(str[i] == str[to]) return false;
}
return true;
}
};
更多关于编程和机器学习资料请关注FlyAI公众号。