字母a-z,数字0-9,现需要其中任意3个作为密码,请输出所有可能组合。

源博文地址:http://blog.csdn.net/wumuzi520/article/details/8087501

字母a-z,数字0-9,现需要其中任意3个作为密码,请输出所有可能组合。首先,看到这问题的时候我们就会想到动态规划。先给出比较简单的例子,就是给定1,2,3,4,5个数字,选出3个数字进行打印。从后往前分析:

先分两种情况,如果选择5,那么剩下的两个可以从1,2,3,4中选择两个出来,如果第二个数字选择4,那么从1,23中选择第三个数字出来,如果不选择4,则冲1,2,3中选择两个出来.....,;如果不选择5,那么就要从1,2,3,4中选择3个出来......这就是其基本思想。

首先可以用递归解决这个问题,但是要找到递归结束的条件。程序中会给予标注。

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
void combination_cursion(int *a,int len,int m,int *out,int out_len)
{
	int i;
	if(m==0)//out中已经存储了m个数字
	{
		for(i=0;i<out_len;i++)
			printf("%d\t",out[i]);
		printf("\n");
		return ;
	}
	
	for(i=len;i>=m;i--)//从前向后依次选定一个,动态规划的体现
	{
		out[m-1]=a[i-1];//选定一个之后
		combination_cursion(a,i-1,m-1,out,out_len);//从前i-1个后选m-1,递归
	}
}
void print_combination_cursion(int *a,int n,int m)
{
	assert(a!=NULL);
	assert(n>=m);
	int *out=(int*)malloc(sizeof(int)*m);
	combination_cursion(a,n,m,out,m);
}
int main()  
{  
    int array[] = {1,2,3,4,5};  
	print_combination_cursion(array,sizeof(array)/sizeof(int),3);   
}  
 
另外一个方法,就是二进制组合算法:

假设从n个数中选取m个进行打印。开辟一个n长度的数组,首先设定前m个位1,其后的都为0。当存储的值为1的时候表示北选中,当存储的值为0的时候表示没有选中。然后从左到右进行扫描,找到第一个“10”的组合,并把其调整为“01”组合,之后把这个调整的“01”组合之前的所有的1移动到最左端(这点与原文有出入),注意,只有第一位即索引值为0的那位为0的时候才需要移动,其他情况不需要移动。

当第一个“1”移动到数组的m-n的位置,即n个“1”全部移动到最右端时,就得到了最后一个组合。    
  例如求5中选3的组合:    
  1   1   1   0   0   //1,2,3    
  1   1   0   1   0   //1,2,4    
  1   0   1   1   0   //1,3,4    
  0   1   1   1   0   //2,3,4    
  1   1   0   0   1   //1,2,5    
  1   0   1   0   1   //1,3,5    
  0   1   1   0   1   //2,3,5    
  1   0   0   1   1   //1,4,5    
  0   1   0   1   1   //2,4,5    
  0   0   1   1   1   //3,4,5

接下来给出程序:

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<windows.h>
void swap(int *a,int *b)
{
	int temp=*a;
	*a=*b;
	*b=temp;
}
void combination(int *a,int n,int m)
{
	assert(n>=m);
	assert(a!=NULL);
	int is_find;
	int i,j,k;
	int *p_table=(int*)malloc(sizeof(int)*n);
	memset(p_table,0,sizeof(int)*n);
	for(i=0;i<m;i++)
		p_table[i]=1;
	is_find=0;
	do
	{
		for(i=0;i<n;i++)
		{
			if(p_table[i]==1)
				printf("%d\t",a[i]);
		}
		printf("\n");
		is_find=0;
		for(i=0;i<n-1;i++)
		{
			if(p_table[i]==1&&p_table[i+1]==0)//找到"10"
			{
				swap(&p_table[i],&p_table[i+1]);//换成"01"
				is_find=1;
				if(p_table[0]==0)
				{
					for(k=0,j=0;k<i;k++)//将交换后"01"之前的1移动到最左端
					{
						if(p_table[k])
						{
							swap(&p_table[k],&p_table[j]);
							j++;
						}
					}
				}
				break;
			}
		}
	}while(is_find);
}
int main()  
{  
    int array[] = {1,2,3,4,5};     
	combination(array,sizeof(array)/sizeof(int),3);
}  
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值