递归从入门到实践(2)

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;
 } 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值