算法学习之数组和字符串
数组和字符串
逆序输出
考虑问题:读入一些整数,逆序输出到一行中。已知整数不超过100个。
我们把每个数都存下来,存放到哪里呢?答案是:数组。
#include <conio.h> #include<stdio.h> #define MAXN 100+10 int a[MAXN]; int main(){ int i,x,n=0; while(scanf("%d",&x)==1){//一直输出 a[n++] = x; } for(i = n-1;i>=1;i--){ printf("%d ",a[i]); } printf("%d\n",a[0]); getch(); return 0; }
逆序输出。
开灯问题
有n盏灯,编号为1~n。第一个人把所有灯打开,第二个人按下所有编号为2的倍数的开关(这些灯将被关掉),第三个人按下所有编号为3的倍数的开关。
(其中关掉的灯将被打开,开着的灯将被关闭),依次类推。一共有k个人,问最后有哪些灯开着?
输入:
n和k,输出开着的灯编号。k<=n<=1000。
样例输入:7 3
样例输出:1 5 6 7
分析:用a[1],a[2],...,a[n]表示编号为1,2,3,...,n的灯是否开着。模拟这些操作即可。
#include <conio.h> #include<stdio.h> #include<string.h> #define MAXN 1000+10 int a[MAXN]; int main(){ int n,k,i,j,first = 1;//n,k用于输入,i,j用于循环,first标记第一个,第一个输出的有些特殊 memset(a,0,sizeof(a));//用于清空数组,引入string.h scanf("%d%d",&n,&k); for(i=1;i<=k;i++){//一共执行k次 for(j=1;j<=n;j++){//每次执行n下 if(j%i==0){//j是i的整数倍,就执行相反动作 a[j] = !a[j]; } } } for(i=1;i<=n;i++){//循环输出 if(a[i]){ if(first){ first = 0; }else{ printf(" "); } printf("%d",i);//输出亮着的灯 } } getch(); return 0; }
蛇形填数
在n*n方阵里填入1,2,...,n*n,要求填成蛇形。例如n=4时方阵为:
10 11 12 1
9 16 13 2
8 15 14 3
7 6 5 4
上面的方阵中,多余的空格只是为了便于观察规律,不必严格输出。n<=8。
分析:二维数组解决之。下,左,上,右,下...
#include <conio.h> #include<stdio.h> #include<string.h> #define MAXN 10 int a[MAXN][MAXN];//定义二维数组 int main(){ int n,x,y,tot = 0;//n表示大小,x,y表示坐标。tot表示起始位置的值。 scanf("%d",&n);//输入n的值 memset(a,0,sizeof(a));//初始化数组 tot = a[x=0][y=n-1] = 1;//第一个值得到了处理 while(tot<n*n){//处理剩下的n*n-1个数 while(x+1<n&&!a[x+1][y]){//满足两个条件,x+1<n并且a[x+1][y]必须为空 a[++x][y] = ++tot;//使用之前先使加一,从第二个处理到最后一个 } while(y-1>=0&&!a[x][y-1]){ a[x][--y] = ++tot;//从最底边的第二个处理到最后一个 } while(x-1>=0&&!a[x-1][y]){ a[--x][y] = ++tot;//从最左边的第二个处理到最后一个 } while(y+1<n&&!a[x][y+1]){ a[x][++y] = ++tot;//从最上面的第二个处理到倒数第二个 } } for(x = 0;x<n;x++){ for(y=0;y<n;y++){ printf("%3d",a[x][y]);//三个作为输出间隙 } printf("\n"); } getch(); return 0;应有编号,之后应有一个空行。最后输出解得总数。 }
小结:判断是关键,这里的循环处理很妙,判断更妙。跟着循环走一遍,分析一遍,发现刚好执行了n*n次,不多不少。
算法的效率非常的高。
字符数组。
竖式问题
找出所有形如abc*de的算式,所有数字都属于一个特定的数字集合。输入数字集合(相邻数字之间没有空格),输出所有竖式。
每个竖式前应有编号,之后应有一个空行。最后输出解的总数。
分析:尝试所有的abc和de,判断是否满足条件。C语言中的字符型用关键字char表示。存储的是字符的ASCII码。
scanf("%s",s)和scanf("%d",&n)类似,它会读入一个不含空格、TAB和回车符的字符串,存入字符数组s。注意,s前面没有&符号。
printf输出到屏幕,fprintf输出到文件,sprintf输出到字符串。
#include <conio.h> #include<stdio.h> #include<string.h> int main(){ int i,ok,abc,de,x,y,z,count=0; char s[20],buf[99]; scanf("%s",s); for(abc = 111;abc<=999;abc++){ for(de = 11;de<=99;de++){ x = abc*(de%10); y = abc*(de/10); z = abc*de; sprintf(buf,"%d%d%d%d%d",abc,de,x,y,z);//写入字符串 ok = 1;//相当于波尔值 for(i = 0;i<strlen(buf);i++){ if(strchr(s,buf[i]) == NULL){ ok = 0; } } //判断所有的是否符合 if(ok){ printf("<%d>\n",++count);//输出个数 printf("%5d\nX%4d\n-----\n%5d\n%4d\n-----\n%5d\n\n",abc,de,x,y,z); } } } printf("The number of solutions = %d\n",count); getch(); return 0; }
小结:作者很强大,太有才了。佩服。
未完待续...