【剑指offer】【搜索和回溯】38. 字符串的排列
题目链接:https://leetcode-cn.com/problems/zi-fu-chuan-de-pai-lie-lcof/
回溯1
class Solution {
public:
vector<string> ans;
string path;
vector<string> permutation(string s) {
path.resize(s.size()); //为path分配大小
sort(s.begin(), s.end()); //对s进行排序
dfs(s, 0, 0, 0);
return ans;
}
/*
u: 当前枚举的位置
start: 用二进制表示某个数是否存在 n个数,用0 ~ 2^(n - 1)表示某个数是否存在;当前这个数应该从哪里开始枚举,上一个数的下一位
state: 存的是哪些数被用过
*/
void dfs(string &s, int u, int start, int state){
//遍历完所有数字
if(u == s.size()){
ans.push_back(path);
return ;
}
//如果是第一个数或者当前数与上一个的数字不同,从头开始枚举
if(!u || s[u] != s[u - 1]) start = 0;
//一个数字与上一个数字相同
for(int i = start; i < s.size(); i++)
if(!(state >> i & 1)) //判断某个数字是否被用过 state表示中第i位是否被用过
{
path[i] = s[u];
dfs(s, u + 1, i + 1, state + (1 << i)); //1左移i位在加上去,相当于把state的第i位变为1
}
}
};
class Solution {
public:
vector<string> res;
string path = "";
vector<string> permutation(string s) {
sort(s.begin(), s.end());
dfs(s, 0);
return res;
}
void dfs(string& s, int u)
{
if(u == s.size())
{
cout << path <<" " << path.size() << endl;
res.push_back(path);
return ;
}
for(int i = 0; i < s.size(); i++)
{
//去重枚举的时候考虑
if(i >= 1 && s[i] == s[i - 1]) continue;
if(s[i] == ' ') continue;
char ch = s[i];
path += ch;
s[i] = ' ';
dfs(s, u + 1);
s[i] = ch;
path.pop_back();
}
}
};
回溯2
字符串不包含重复字符
- 求所有可能出现在第一个位置的字符,把第一个字符和后面所有的字符交换
- 固定第一个字符,求后面字符的排列(仍然按照1,2来求);
不包含重复字符
#include <iostream>
using namespace std;
const int N = 100010;
char a[N];
void dfs(char *pStr, char *pBegin)
{
if(*pBegin == '\0') printf("%s ", pStr);
else
{
for(char *pCh = pBegin; *pCh != '\0'; ++pCh)
{
swap(*pCh, *pBegin);
dfs(pStr, pBegin + 1);
swap(*pCh, *pBegin);
}
}
}
void permutation(char *s)
{
if(s == nullptr) return ;
dfs(s, s);
printf("\n");
}
int main() {
scanf("%s", &a);
permutation(a);
return 0;
}
class Solution {
public:
vector<string>res;
vector<string> permutation(string s) {
int cursor=0;
permutation(s,cursor);
return res;
}
void permutation(string &s,int cursor){
if(cursor==s.size() - 1){
res.push_back(s);
}
else{
for(int i=cursor;i<s.size();i++){
if(judge(s,cursor,i))continue; //从cursor开始,遍历不重复的字符
swap(s[cursor],s[i]);
permutation(s,cursor+1);
swap(s[cursor],s[i]);
}
}
}
bool judge(string& s, int start, int end) {
for (int i = start; i < end; ++i) {
if (s[i] == s[end]) return true;
}
return false;
}
};
知识的价值不在于占有,而在于使用