1.打印一个字符串的全部子序列
way:选or不选,void go(string&s, int index, string path)中的path不能是引用,不然就会被影响,不使用引用就是为了他不影响我,我不影响他,形参果然是另外一个和我长得一样的人,但不是我。
#include<iostream>
#include<vector>
#include<string>
using namespace std;
//现在来的位置是s的index位置,之前做过的选择拼成的字符序列在path上
void go(vector<string>&result, string& s, int index, string path)
{
if(index == s.size())
{
result.push_back(path);
return;
}
//不选index位置处的字符
go(result, s, index+1, path);
path = path + s[index];
//选index位置处的字符
go(result, s, index+1, path);
}
void print(vector<string> vec)
{
for(auto s:vec)
{
cout<<s<<endl;
}
}
vector<string> getSubs(string s)
{
string path="";
vector<string> result;
go(result,s,0,path);
return result;
}
int main()
{
string s="abcd";
print(getSubs(s));
system("pause");
return 0;
}
如果非要写引用的话也可以这样写消除他对我的影响。
//现在来的位置是s的index位置,之前做过的选择拼成的字符序列在path上
void go(vector<string>&result, string& s, int index, string& path)
{
string tmp=path;
if(index == s.size())
{
result.push_back(path);
return;
}
//不选index位置处的字符
go(result, s, index+1, path);
path = path + s[index];
//选index位置处的字符
go(result, s, index+1, path);
path=tmp;
}
2.打印一个字符串的全部子序列,要求不要出现重复字面值的子序列。
way:用set去重。
#include<iostream>
#include<string>
#include<set>
using namespace std;
//现在来的位置是s的index位置,之前做过的选择拼成的字符序列在path上
void go(set<string>&result, string& s, int index, string path)
{
if(index == s.size())
{
result.insert(path);
return;
}
//不选index位置处的字符
go(result, s, index+1, path);
path = path + s[index];
//选index位置处的字符
go(result, s, index+1, path);
}
void print(set<string> vec)
{
for(auto s:vec)
{
cout<<s<<endl;
}
}
set<string> getSubs(string s)
{
string path="";
set<string> result;
go(result,s,0,path);
return result;
}
int main()
{
string s="abccd";
print(getSubs(s));
system("pause");
return 0;
}
3.打印一个字符串的全部排列。
way:排列就不是选不选的问题了,而是先选谁后选谁的问题了,因为必须全都要选。
#include<iostream>
#include<vector>
#include<string>
#include<map>
using namespace std;
void go(vector<string>&result, string& s, string &path, map<int,bool>&vis)
{
string tmp = path;
if(path.size() == s.size())
{
result.push_back(path);
return;
}
for(int i=0; i<s.size(); i++)
{
if(!vis[i])
{
vis[i]=true;
path += s[i];
go(result, s, path, vis);
path =tmp;
vis[i]=false;
}
}
}
vector<string> permutation(string s)
{
string path="";
vector<string> result;
map<int,bool>vis;
go(result,s,path,vis);
return result;
}
void print(vector<string> vec)
{
for(auto s:vec)
{
cout<<s<<endl;
}
cout<<vec.size()<<endl;
}
int main()
{
string s="abcd";
print(permutation(s));
system("pause");
return 0;
}
way2:用了rest表示剩余字符集合的方法,其实和上面的方法是一样的(上面是字符串s不变,用vis记录访问过的字符),这里是用了rest剩余的想法。
#include<iostream>
#include<vector>
#include<string>
using namespace std;
//rest为剩余的没选过的字符序列,path中放的是选过的字符序列,result是结果集
void go(vector<string>&result, string& rest, string path)
{
if(rest.empty())
{
result.push_back(path);
return;
}
//从rest中开始选字符
for(int i=0; i<rest.size(); i++)
{
char ch = rest[i];
//rest中移除当前字符,path加上当前字符
rest.erase(rest.begin()+i);
go(result, rest, path + ch);
//恢复rest中的字符, 尝试选择下一个字符(一定要恢复在i位置,因为for是rest的循环,不然就在循环的过程中改变rest了)
rest.insert(rest.begin()+i, ch);
}
}
vector<string> permutation2(string s)
{
vector<string> result;
string path="";
go(result, s, path);
return result;
}
void print(vector<string>vec)
{
for(auto num: vec)
{
cout<<num<<endl;
}
cout<<vec.size()<<endl;
}
int main()
{
print(permutation2("abcde"));
system("pause");
return 0;
}
way3:把后面的字符往前换,另一种角度,return的条件需要注意下。
#include<iostream>
#include<vector>
#include<string>
using namespace std;
void swap(char& a, char& b)
{
char tmp =a;
a=b;
b=tmp;
}
void go(vector<string>&result, string &s, int index)
{
if(index == s.size())
{
result.push_back(s);
return;
}
for(int i=index; i<s.size(); i++)
{
swap(s[index], s[i]);
go(result, s, index+1);
swap(s[i], s[index]);
}
}
vector<string> permutation3(string s)
{
vector<string> result;
go(result, s, 0);
return result;
}
void print(vector<string>vec)
{
for(auto num: vec)
{
cout<<num<<endl;
}
cout<<vec.size()<<endl;
}
int main()
{
print(permutation3("abcde"));
system("pause");
return 0;
}
way3的去重版,abccd这样子的去重,在当前选择的时候不能选重复的字符,vis的作用。
#include<iostream>
#include<vector>
#include<string>
#include<map>
using namespace std;
void swap(char& a, char& b)
{
char tmp =a;
a=b;
b=tmp;
}
void go(vector<string>&result, string &s, int index)
{
if(index == s.size())
{
result.push_back(s);
return;
}
map<char,bool>vis; //去重
for(int i=index; i<s.size(); i++)
{
if(!vis[s[i]])
{
vis[s[i]]=true;
swap(s[index], s[i]);
go(result, s, index+1);
swap(s[i], s[index]);
}
}
}
vector<string> permutation3(string s)
{
vector<string> result;
go(result, s, 0);
return result;
}
void print(vector<string>vec)
{
for(auto num: vec)
{
cout<<num<<endl;
}
cout<<vec.size()<<endl;
}
int main()
{
print(permutation3("abccd"));
system("pause");
return 0;
}
way2的去重版,一样的道理,在当前选择的时候不能选重复的字符,vis的作用。
#include<iostream>
#include<vector>
#include<string>
#include<map>
using namespace std;
//rest为剩余的没选过的字符序列,path中放的是选过的字符序列,result是结果集
void go(vector<string>&result, string& rest, string path)
{
if(rest.empty())
{
result.push_back(path);
return;
}
//去重
map<char,bool>vis;
//从rest中开始选字符
for(int i=0; i<rest.size(); i++)
{
char ch = rest[i];
if(!vis[ch])
{
vis[ch]=true;
//rest中移除当前字符,path加上当前字符
rest.erase(rest.begin()+i);
go(result, rest, path + ch);
//恢复rest中的字符, 尝试选择下一个字符(一定要恢复在i位置,因为for是rest的循环,不然就在循环的过程中改变rest了)
rest.insert(rest.begin()+i, ch);
}
}
}
vector<string> permutation2(string s)
{
vector<string> result;
string path="";
go(result, s, path);
return result;
}
void print(vector<string>vec)
{
for(auto num: vec)
{
cout<<num<<endl;
}
cout<<vec.size()<<endl;
}
int main()
{
print(permutation2("abccd"));
system("pause");
return 0;
}
way的去重版,一样的道理,在当前选择的时候不能选重复的字符,chVis的作用。
#include<iostream>
#include<vector>
#include<string>
#include<map>
using namespace std;
void go(vector<string>&result, string& s, string &path, map<int,bool>&vis)
{
string tmp = path;
if(path.size() == s.size())
{
result.push_back(path);
return;
}
map<char,bool>chVis;
for(int i=0; i<s.size(); i++)
{
if(!vis[i] && !chVis[s[i]])
{
chVis[s[i]]=true;
vis[i]=true;
path += s[i];
go(result, s, path, vis);
path =tmp;
vis[i]=false;
}
}
}
vector<string> permutation(string s)
{
string path="";
vector<string> result;
map<int,bool>vis;
go(result,s,path,vis);
return result;
}
void print(vector<string> vec)
{
for(auto s:vec)
{
cout<<s<<endl;
}
cout<<vec.size()<<endl;
}
int main()
{
string s="abccd";
print(permutation(s));
system("pause");
return 0;
}