算法学习之数组和字符串

数组和字符串

逆序输出
考虑问题:读入一些整数,逆序输出到一行中。已知整数不超过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;
}

小结:作者很强大,太有才了。佩服。

未完待续...

posted @ 2013-07-30 23:06  TBHacker  阅读(594)  评论(0编辑  收藏  举报