C博客作业04--数组

1. 本章学习总结

1.1 思维导图

1.2 本章学习体会及代码量学习体会

1.2.1 学习体会

这几周学习了数组,一维数组,二维数组,字符数组,前一个题集还没做完,后一个题集就又发布了,当场去世,可能因为题目难度也在增加,然后有些懒,题目一直放着没有好好去做,都是等老师讲完有了思路,再根据老师的思路把代码打一遍。这一点自我检讨一下。学习了数组,并且学了几种排序方法,之前的一些题目也可以改用数组的方法来做。感觉数组有些题目有思路做起来,也有点懵懵的,不能一遍过,都需要调试一下才知道自己的问题出在哪。数组这块的内容还是很重要的,所以我应该要把知识盲区都弄懂,并且累计一些做题思路。而且题集也不能一拖再拖了,遇到难题也不应该是躲避了,希望在接下去的时间里,我可以把它们全解决掉。

1.2.2 代码累计

2. PTA总分

2.1 截图PTA中数组题目集的排名得分



2.2 我的总分:390

一维数组:175
二维数组:105
字符数组:110

3. PTA实验作业

3.1 PTA题目1

数组循环左移 
本题要求实现一个对数组进行循环左移的简单函数:
一个数组a中存有n(>0)个整数,在不允许使用另外数组的前提下,将每个整数循环向左移m(≥0)个位置

3.1.1 算法分析

定义i,j,n,m,temp
输入n,m
输入n个数存入数组a
for i=0 to m do
    temp=a[0]
    for j=0 to n-1 do
        a[j]=a[j+1]
    a[n-1]=temp
    end for
end for
按照要求格式输出

3.1.2 代码截图

#include<stdio.h>
int main()
{
	int n,m,i,j,temp;
	scanf("%d%d",&n,&m);
	int a[n];
	for(i=0;i<n;i++)
		scanf("%d",&a[i]);
	for(i=0;i<m;i++)                 //左移次数
	{
		temp=a[0];                //先用temp储存a[0]
		for(j=0;j<n-1;j++)
	    	a[j]=a[j+1];                //各数往前移
	  a[n-1]=temp;                  //将a[0]放到最后一位
	}
	for(i=0;i<n;i++)
	{
		if(i<n-1)
			printf("%d ",a[i]);
		else
			printf("%d",a[i]);
	}
	return 0;
}

3.1.3 PTA提交列表及说明

Q1:刚开始做,挺有思路的但是感觉代码质量很差,而且有一两个点一直过不了
A1:后来老师在课上讲了这题,瞬间有种顿悟的感觉,好方法就要累积下来

3.2 PTA题目2

找鞍点 
一个矩阵元素的“鞍点”是指该位置上的元素值在该行上最大、在该列上最小。

3.2.1 算法分析

定义i,j,k,n,temp,flag,count=0
输入n
输入n行n列的二维数组
用两层for循环遍历这个二维数组
	初始化flag,temp为0
	for k=0 to n do
		if a[i][j]<a[i][k] then
			flag=1
		end if
	end for
	for k=0 to n do
		if a[i][j]>a[k][j] then 
			temp=1
		end if
	end for
	if flag==0 && temp==0
		count++
		输出 i j
	end if 
end for
if count==0 then
	输出 NONE

3.2.2 代码

改前

#include<stdio.h>
int main()
{
  int i,j,k,temp;
  int flag=0,count=0;
  int n;
  scanf("%d",&n);
  int a[n][n];
  for(i=0;i<n;i++)
  {
    for(j=0;j<n;j++)
    {
      scanf("%d",&a[i][j]);
    }
  }
  int max;
  for(i=0;i<n;i++)
  {
  	flag=0;
    max=a[i][0];
    for(j=0;j<n;j++)
    {
      if(a[i][j]>max)                 //找出行中最大值
      {
      	max=a[i][j];
        temp=j;
      }
    }
    for(k=0;k<n;k++)
    {
      if(a[k][temp]<max)         //在该行所在的列判断是否为最小值
      {
      	flag=1;
      	break;
      }
    }
    if(flag==0)
    {
    	printf("%d %d\n",i,temp);
    	count++;
	}
  }
  	if(count==0)
  		printf("NONE");
}

改后

#include<stdio.h>
int main()
{
  int i,j,k,temp,flag;
  int count=0;
  int n;
  scanf("%d",&n);
  int a[n][n];
  for(i=0;i<n;i++)
  {
    for(j=0;j<n;j++)
    {
      scanf("%d",&a[i][j]);
    }
  }
  for(i=0;i<n;i++)
  {
    for(j=0;j<n;j++)
    {
      flag=0;
      temp=0;
      for(k=0;k<n;k++)
      {
        if(a[i][j]<a[i][k])
          flag=1;                   //不是行中最大的,令flag=1
      }
      for(k=0;k<n;k++)
      {
        if(a[i][j]>a[k][j])
          temp=1;                 //不是列中最大的,令temp=1
      }
      if(flag==0&&temp==0)
      {
        count++;
        printf("%d %d",i,j);
      }
    }
  }
  if(count==0)
  		printf("NONE");
  	return 0;
}

3.2.3 PTA提交列表及说明

Q1:一开始的做法,是想先找出该行上最大的值,然后在判断所在的列中它是不是最小的,但是有个测试点过不了,就是有两个一样的极值的时候,它会两个都输出
A1:后来换了个想法,判断该行中,是否有比它更大的,如果有令flag=1,再判断该列中是否有比它更小的,有的话令temp=1,当flag和temp都为0时就存在鞍点了
A2:虽然还是存在两个一样极值时,它都输出了,可是整个都过了,这有bug啊!

3.3 PTA题目3

查验身份证
一个合法的身份证号码由17位地区、日期编号和顺序编号加1位校验码组成。
按照输入的顺序每行输出1个有问题的身份证号码。这里并不检验前17位是否合理,只检查前17位是否全为数字且最后1位校验码计算准确。如果所有号码都正常,则输出All passed。
校验码的计算规则如下:
首先对前17位数字加权求和,权重分配为:{7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2};然后将计算的和对11取模得到值Z;最后按照以下关系对应Z值与校验码M的值:
Z:0 1 2 3 4 5 6 7 8 9 10
M:1 0 X 9 8 7 6 5 4 3 2

3.3.1 算法分析

定义整型变量N,i,j,k,count,count1,整型数组ch,整型数组sum
定义字符型数组num,字符型数组M,字符型数组Z 
输入N 
for i=0 to N do
	初始化count=0,sum[i]=0
	输入字符串
	for j=0 to 17 do
	 	if num[i]大于0并且小于9               
			次数count加1
			sum[i]+=((num[j]-'0')*(ch[j]))     //根据题目要求计算和 
		end if
	end for
	if 满足是数字的次数不足17次
		输出num数组
	else
		for k=0 to 11 do
			if  sum[i]%11==Z[k]                  //将它得到的模和Z数组比较,找出对应M数组中的位置 K 
	 			if (num[17]-'0')!=M[k]       //将身份证最后一位和M数组中的第k位比较 
	 				输出num数组
				else
					身份证合法的个数加1
			end if
		end for
	if 两个条件都满足即是合法身份证的个数和输入查验的个数一样
		输出All passed
	end if
end for	

3.3.2 代码

#include<stdio.h>
int main()
{
  int N;
  scanf("%d",&N);
  getchar();
  int sum[N];
  char num[19],X;
  char M[11]={1,0,'X'-'0',9,8,7,6,5,4,3,2};//题目中的 Z值 
  char Z[11]={0,1,2,3,4,5,6,7,8,9,10};//题目中的校验码M 
  int ch[19]={7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2};//题目中权重分配 
  int i,j,k;
  int count,count1=0;
  for(i=0;i<N;i++)
  {
  	count=0;
  	sum[i]=0;
  	gets(num);
  	for(j=0;j<17;j++)
  	{
  		if(num[j]<='9'&&num[j]>='0')
  		{
  			count++;
  			sum[i]+=((num[j]-'0')*(ch[j]));
		}
	}
	if(count!=17)                                               //判断前十七个数是否为数字 
	{
		puts(num);
	}
	else
	{
		for(k=0;k<11;k++)
		{
			if(sum[i]%11==Z[k])                      //将它得到的模和Z数组比较,找出对应M数组中的位置 K 
			{
				if((num[17]-'0')!=M[k])          //将身份证最后一位和M数组中的第k位比较 
				{
					puts(num);
				}
				else 
				{
					count1++;                    //号码正确的个数 
				}
			}
		}
	}if(count1==N)
	printf("All passed");
  }
}

3.3.3 PTA提交列表及说明

Q1:又是提交了好多次,测试点一两个过不了,还越改越不对,绝望.jpg
A1:慢慢调试,发现了好多问题,像第二次进去时,count,sum之类的没有初始化,还有字符数组时忘记减去‘0’,导致值算出来是错的,看来之前的测试点也是混过去的了。
Q2:改得差不多了,以为这次应该对了,可是还有个最大n的测试点不对,请教了一下大佬,然后发现是X的问题,在我把它们都转成数字的同时,没有考虑到X对应的那个值也被转化了
A2:本来还想着分类讨论一下,然后大佬告诉我直接在M数组改一下就好了,emmm,有道理,觉得自己智商堪忧了,后来终于过了,感动.jpg

4. 代码互评

4.1 代码截图

同学代码

我的代码

4.2 两者的不同

1.整体思路不同:同学的思路是用hash数组来找相同的数字,而我的思路是遍历两个数组直接进行比较
2.对方优点:代码更加灵活,可扩展性也比较好
3.我的优点:思路比较直接,易懂
posted @ 2018-12-08 21:26  Hyjjing  阅读(156)  评论(3编辑  收藏  举报