持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第20天,点击查看活动详情
一、题目
描述
输入一个长度为 n 字符串,打印出该字符串中字符的所有排列,你可以以任意顺序返回这个字符串数组。
例如输入字符串ABC,则输出由字符A,B,C所能排列出来的所有字符串ABC,ACB,BAC,BCA,CBA和CAB。
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
vector<string> permutation(string& str) {
}
int main(int, char*[])
{
string str = "aab";
vector<string> res = permutation(str);
for(string s : res){
cout << s << endl;
}
}
二、分析
由题意可知,排列问题是典型的递归应用场景之一,不过这里又有一点点特殊,因为这里需要排除重复,这个有一点难度,因为重复的情况各种各样,要兼容所有情况,只能建立hash表,但是这样效率就会大打折扣。
那有没有什么办法可以降低重复情况呢?
首先想到重复是因为字符重复导致,而导致情况各种各样的原因是重复字符分布无规律,知道问题,就能解决问题。
重复字符分布无规律,那我们就排个序。
字符重复,我们就在排列的时候检测一下,重复排列会出现两次,可以排除第一次重复,也可以排除第二次重复。
三、模拟
- 1
- 1 2 第一次重复
- 1 2 3
- 1
- 1 3
- 1 3 2
- 2 第二次重复,排除
- 3
- 3 1
- 3 1 2 第一次重复
- 3 2 第二次重复,排除
四、实现
void permutationDfs(vector<string>& res, string& str, string& temp, vector<int>& vis){
if(temp.length() == str.length()){
res.push_back(temp);
return;
}
for(int i = 0; i < str.length(); ++i){
if(vis[i]) continue;
if(i > 0 && str[i - 1] == str[i] && !vis[i - 1]) continue;
vis[i] = 1;
temp.push_back(str[i]);
permutationDfs(res, str, temp, vis);
vis[i] = 0;
temp.pop_back();
}
}
vector<string> permutation(string& str) {
std::sort(str.begin(), str.end());
vector<int> vis(str.size(), 0);
vector<string> res;
string temp;
permutationDfs(res, str, temp, vis);
return res;
}
五、结言
要想解决问题,首先得知道问题出在哪里,然后再对症下药,就能药到病除。
创作不易,留个赞再走吧!如果对文章内容有任何指正,欢迎评论!