NTES 2012 打印字母序列
打印以下序列:
(a),(b),(c),(d),(e)........(z)
(a,b),(a,c),(a,d),(a,e)......(a,z),(b,c),(b,d).....(b,z),(c,d).....(y,z)
(a,b,c),(a,b,d)....(a,b,z),(a,c,d)....(x,y,z)
....
(a,b,c,d,.....x,y,z)
思路一:每个集合可以看做一个数,根据字母是26进制的特性,生成所有数(去掉一些),再排序输出。但最大的数可以到达26^26,复杂度太大。且不知如何实现。
思路二:用到排列组合的思想,用递归代替26重循环。
View Code
1 #include<iostream>
2 using namespace std;
3 #define LEN 6
4 int buf[LEN];
5 bool flag = false;
6
7 void show(int len)
8 {
9 cout<<"(";
10 for(int i=0; i<=len; i++)
11 {
12 char c='a'+buf[i];
13 cout<<c;
14 if(i!=len)
15 cout<<",";
16 }
17 cout<<")";
18 if(flag)cout<<",";
19 else cout<<endl;
20 }
21 void gene(int first,int deepth,int index) //打印首字母为'a'+first,长度为deppth的所有集合,这样的集合有多少个?
22 {
23 buf[index]=first;
24 if(deepth==1) //打印一个长度为最先传进来的deepth集合,相当于到了LEN层循环的最里层,可以打印了
25 {
26 show(index);
27 }
28 for(int i=first+1; i<LEN; i++) //其实就是递归打印首字每加1,长度减1的所有集合
29 gene(i,deepth-1,index+1);
30 }
31 void solve()
32 {
33 for(int i=0; i<LEN; i++) //用i控制每次打印的长度,从1到LEN
34 {
35 flag=true;
36 for(int j=0; j<LEN; j++) //用j控制每次长度一定的时候的首字母的变化,从a变化的'a'+LEN(注意,其实没变化到'a'+LEN,只变化的'a'+LEN-i,即写成i+j<LEN更准确)
37 {
38 if(j==LEN-i-1)
39 flag=false;
40 gene(j,i+1,0);
41 }
42 }
43 }
44 int main()
45 {
46
47 solve();
48 return 0;
49 }
迭代的是人,递归的是神。
这个题目我想了两天,递归关键是要理解其思想,洞穿其过程。
接下来要加强递归的题目的训练。
精简版,方便阅读。感谢神一样的男人,阳神!
View Code
1 #include <stdio.h>
2 #include <string.h>
3 #include <stdlib.h>
4
5 #define LEN 6
6 int buf[LEN];
7
8 void show(int ind)
9 {
10 printf("(");
11 for(int i = 0; i <= ind; ++i)
12 printf("%c", 'a'+buf[i]);
13 printf(")");
14 }
15 void gene(int first, int len, int ind) //从'a'+first开始生成长度为len的序列,当前生成字母保存在buf[ind]
16 {
17
18 buf[ind] = first;
19 if(len == 1)
20 show(ind);
21 for(int i = first + 1; i < LEN; ++i )
22 gene(i, len-1, ind+1);
23 }
24 void Solve()
25 {
26 for(int i = 0; i < LEN; ++i) //生成的集合大小
27 {
28 for(int j = 0; j+i < LEN; ++j) //生成的第一字母
29 gene(j,i+1,0);
30 printf("\n");
31 }
32 }
33 int main()
34 {
35 Solve();
36 return 0;
37 }