1.2”逐步生成结果“类问题之非数值型
此时就要用容器去装了
-生成一点,装一点,所谓迭代就是慢慢改变
例子
- cc9.6合法括号
- cc9.4非空子集
- cc9.5字符串(集合)全排列
为什么写成递归
因为递归有更强的表达力
题解
cc9.6合法括号
实现一种算法,打印n对括号的全部有效组合(左右括号正确配对)
实例
输入:3
输出:()()(), (()()), ()(()), (())(), ((()))
思路:()可以有3中组合,左右包,其中左右相同为()(),包为(())
()()左右包分别为()()(), (()())
(())左右包分别为()(()), (())(), ((())))
递归
#include<iostream>
#include<set>
using namespace std;
set<string> solve(int n)
{
set<string> s1;
if(n==1)
{
s1.insert("()");
return s1;
}
set<string> s2=solve(n-1);
set<string>::iterator iter=s2.begin();
for(;iter!=s2.end();iter++)
{
s1.insert("()"+*iter);
s1.insert(*iter+"()");
s1.insert("("+*iter+")");
}
return s1;
}
int main()
{
int n;
cin>>n;
set<string> iset=solve(n);
set<string>::iterator iterr=iset.begin();
for(;iterr!=iset.end();iterr++)
{
cout<<*iterr<<endl;
}
return 0;
}
迭代
#include<iostream>
#include<set>
using namespace std;
int main()
{
int n;
cin>>n;
set<string> set1;
set<string> set2;
set2.insert("()");
for(int i=1;i<n;i++)
{
set1=set2;//每次把s2赋值给s1,再进行左右包操作
set<string>::iterator iter=set1.begin();
set2.clear();//s2保存每层的方案
for(;iter!=set1.end();iter++)
{
set2.insert("()"+*iter);
set2.insert(*iter+"()");
set2.insert("("+*iter+")");
}
}
set<string>::iterator iterr=set2.begin();
for(;iterr!=set2.end();iterr++)
{
cout<<*iterr<<endl;
}
return 0;
}
cc9.4非空子集
编写一个方法,返回某集合的所有子集
#include<iostream>
#include<vector>
using namespace std;
void solve(vector<string> nums,vector<vector<string> >&result,vector<string>&item,int n)
{
if(n>=nums.size())return;
item.push_back(nums[n]);
result.push_back(item);
solve(nums,result,item,n+1);
item.pop_back();
solve(nums,result,item,n+1);
}
int main()
{
string num[]={"A","B","C"};
vector<string> nums(num,num+3);
vector<vector<string> >result;
vector<string>item;
solve(nums,result,item,0);
for(int i=0;i<result.size();i++)
{
for(int j=0;j<result[i].size();j++)
{
cout<<result[i][j];
}
cout<<endl;
}
return 0;
}
迭代法
#include<iostream>
#include<vector>
using namespace std;
int main()
{
string num[]={"A","B","C"};
vector<string> nums(num,num+3);
vector<vector<string> >result;
vector<string>item;
item.push_back("");
result.push_back(item);//初始化,记录空集
for(int i=0;i<nums.size();i++)//每个元素加或者不加
{
vector<vector<string> >new_result;//新的结果集=现有的每种情况加+现有的每种情况不加
new_result=result; //不加
for(int j=0;j<result.size();j++)//加
{
vector<string>clone;
for(int k=0;k<result[j].size();k++)
{
clone.push_back(result[j][k]);
}
clone.push_back(nums[i]);
new_result.push_back(clone);
}
result.assign(new_result.begin(),new_result.end());//相当于result=new_result
}
for(int i=0;i<result.size();i++)//输出
{
for(int j=0;j<result[i].size();j++)
{
cout<<result[i][j];
}
cout<<endl;
}
return 0;
}
二进制法
#include<iostream>
#include<vector>
#include<math.h>
using namespace std;
int main()
{
string num[]={"A","B","C"};//A代表001,B代表010,C代表100
vector<string> nums(num,num+3);
vector<string> item;
vector<vector<string> >result;
for(int i=1;i<=pow(2,nums.size())-1;i++)
{
item.clear();
for(int j=0;j<nums.size();j++)
{
if((i>>j)&1==1)item.push_back(nums[j]);
}
result.push_back(item);
}
for(int i=0;i<result.size();i++)//输出
{
for(int j=0;j<result[i].size();j++)
{
cout<<result[i][j];
}
cout<<endl;
}
return 0;
}
cc9.5字符串(集合)全排列
迭代法(字符串大于等于4输出有误???)
#include<iostream>
#include<vector>
using namespace std;
vector<string> solve(string str)
{
int n=str.size();
vector<string>vec;
string s;
s.push_back(str.at(0));
vec.push_back(s);//初始化,包含第一个字符
for(int i=1;i<n;i++)
{
vector<string>vec_new;
char c=str.at(i);
for(int j=0;j<vec.size();j++)
{
string s;
s.push_back(c);
string new_vec_j=vec[j];
string new_str=new_vec_j.insert(0,s);//每个元素前孔位加str.at(i)
vec_new.push_back(new_str);
new_vec_j=vec[j];
int end=vec.end()-vec.begin();//每个元素后孔位加str.at(i)
new_str=new_vec_j.insert(end,s);
vec_new.push_back(new_str);
for(int k=1;k<vec[j].size();k++) //每个元素中间孔位加str.at(i)
{
new_vec_j=vec[j];
new_str=new_vec_j.insert(k,s);
vec_new.push_back(new_str);
}
}
vec=vec_new;
}
return vec;
}
int main()
{
vector<string>vec=solve("ABC");
for(int i=0;i<vec.size();i++)
{
cout<<vec[i]<<endl;
}
return 0;
}
交换法,递归回溯法(dfs)
#include<iostream>
#include<vector>
#include<string.h>
using namespace std;
vector<string> res;
void swap(char arr[],int i,int j)
{
char temp=arr[i];
arr[i]=arr[j];
arr[j]=temp;
}
void getPermutation(char arr[],int k) //k看作下标
{
if(k==strlen(arr))res.push_back(arr);//下标越界,返回
for(int i=k;i<strlen(arr);i++)
{
swap(arr,i,k);//操作,将arr数组中的下标>=k的字符与k位置的字符交换
getPermutation(arr,k+1);
swap(arr,i,k);//回溯,因为公用同一数组arr,所以操作后要回溯
}
}
int main()
{
char str[]="ABCD";
getPermutation(str,0);
for(int i=0;i<res.size();i++)
{
cout<<res[i]<<endl;
}
return 0;
}
#include<iostream>
#include<vector>
#include<string>
#include<string.h>
using namespace std;
int count=0;
int k=6;
int countt(char arr[],char ch)
{
int cnt=0;
for(int i=0;i<strlen(arr);i++)
{
if(arr[i]==ch)
cnt++;
}
return cnt;
}
void permutation(string prefix,char arr[])
{
if(prefix.length()==strlen(arr))//出口:前缀长度=字符串长度
{
count++;
if(count==k)
{
cout<<"------:"+prefix<<endl;
return ;
}
}
for(int i=0;i<strlen(arr);i++)//每次都从头遍历,只要可用的字符,就加在前缀上
{
char ch=arr[i];
char * str;
str=(char*)prefix.c_str();
if(countt(str,ch)<countt(arr,ch))//可用字符ch:前缀中ch的个数小于字符串中ch的个数
permutation(prefix+ch,arr);
}
}
int main()
{
char arr[]="ABC";
permutation("",arr);
return 0;
}