C语言程序设计之 数组2020-10-28 整理:
第一题:求最小数与第一个数交换
【问题描述】
输入一个正整数n (1<n<=100),再输入n个整数,将最小值与第一个数交换,然后输出交换后的n 个数。
【输入形式】
第一行,一个正整数n
第二行,n个由空格隔开的整数
【输出形式】
最小数与第一个数交换后的n的整数
【样例输入】
5
8 2 5 1 4
【样例输出】
1 2 5 8 4
#include <stdio.h>
#include <stdlib.h>
int main()
{
int n,i,j,k;
int x[100];
scanf("%d",&n);
//数组元素
for(i=0;i<n;i++){
scanf("%d",&x[i]);
}
//printf("%d",t);
k = 0;
for(j=1;j<n;j++){
if(x[k]>x[j]){
k=j;
}
}
//交换
int t = x[0];
x[0] = x[k];
x[k] = t;
for(k=0;k<n;k++){
printf("%d ",x[k]);
}
return 0;
}
解释:
数组循环存储不解释,很好理解;
首先我们假设最小值的下标为0,即:k=0;
我们所需要做的就是把后面的数与最小值进行比较,如果还有比最小值小的值,则交换下标;
k = 0;
for(j=1;j<n;j++){
if(x[k]>x[j]){
k=j;
}
}
找到最小值的下标,也就找到了最小值的值,然后进行最小值与第一个数进行交换;
//交换
int t = x[0];
x[0] = x[k];
x[k] = t;
两个元素的交换需要通过中间变量(t)来存储,要不然会有数据被覆盖掉,得不到正确的值;
最好循环遍历整个数组即可。
第二题:求一组数的编号
【问题描述】
对数组A中的N(0<N<100)个互不相同的整数从小到大进行连续编号,要求不能改变数组A中元素的顺序。
如A=(78,42,-34,94,25)则输出为(4,3,1,5,2)。个数N和数组中元素要求从键盘输入。
【输入形式】
第一行,一个整数N
第二行n个空格隔开的整数
【输出形式】
按顺序输出每个整数的编号,编号间用逗号分隔
【样例输入】
5
78 42 -34 94 25
【样例输出】
4,3,1,5,2
#include <stdio.h>
int main() {
int x[100];
int a[100];
int n;
int num;
int count=0;
scanf("%d",&n);
//输入数据存入数组中
for (int i = 0; i < n; ++i) {
scanf("%d",&x[i]);
//初始化
a[i]=1;
}
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) {
if (x[i]>=x[j]){
num ++;
}
}
a[i] =num;
num =0;
}
for (int i = 0; i < n; ++i) {
count++;
if(count==n){
printf("%d",a[i]);
} else{
printf("%d,",a[i]);
}
}
return 0;
}
解释:
判断元素的编号,实际是比大小;
定义两个数组,一个存储输入的元素,一个存储记录比较的次数;
对两个数组进行初始化;
两层循环,将第一个元素与每个元素进行比较,如果符合条件的进行记录num++;
每次结束后在第一层循环里记录num的值,并保存到a[]数组中;
将num清零,重复上述操作;
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) {
if (x[i]>=x[j]){
num ++;
}
}
a[i] =num;
num =0;
}
为了满足输出的操作,需要输出a[]数组时判断最后的值,
for (int i = 0; i < n; ++i) {
count++;
if(count==n){
printf("%d",a[i]);
} else{
printf("%d,",a[i]);
}
}
第三题:跳一跳
【问题描述】跳一跳规则如下:玩家每次从当前方块跳到下一个方块,如果没有跳到下一个方块上则游戏结束。 如果跳到了方块上,但没有跳到方块的中心则获得1分;跳到方块中心时,若上一次的得分为1分或这是本局游戏的第一次跳跃则此次得分为2分,否则此次得分比上一次得分多两分(即连续跳到方块中心时,总得分将+2,+4,+6,+8...)。
现在给出一个人跳一跳的全过程,请你求出他本局游戏的得分(按照题目描述的规则)。
【输入格式】
输入包含多个数字,用空格分隔,每个数字都是1,2,0之一,1表示此次跳跃跳到了方块上但是没有跳到中心,2表示此次跳跃跳到了方块上并且跳到了方块中心,0表示此次跳跃没有跳到方块上(此时游戏结束)。
【输入形式】对于所有评测用例,输入的数字不超过30个,保证0正好出现一次且为最后一个数字。
【输出形式】一个整数,表示得分。
【样例输入】1 1 2 2 2 1 1 2 2 0
【样例输出】22
【样例说明】22=1+1+2+4+6+ 1+1+2+4
#include <stdio.h>
int main() {
int n;
//统计得分,记录得分个数
int sum=0,temp=0;
//题目知不超过30
for (int i = 0; i<30; i++) {
scanf("%d",&n);
if(n==0){
break;
}
if (n==1){
//计数清零
temp=0;
sum +=1;
}
if(n==2){
temp +=1;
sum +=temp*2;
}
}
printf("%d",sum);
return 0;
}
解释:
判断个数问题;
如果:
- =0:退出循环
- =1:统计得分,得分个数初始化为0,为后面=2做准备
- =2:统计得分个数,累加2与得分个数的乘积
第四题:开灯问题
【问题描述】有n盏灯,编号为1-n。第一个人把所有灯打开,第2个人按下所有编号为2倍数的开关(这些灯将被关掉),第3个人按下所有编号为3的倍数的开关(其中关掉的灯将被打开,开着的灯将被关闭),依此类推。一共有k个人,问最后有哪些灯开着?
输入 n和k,输出开着灯的编号。
【输入形式】两个整数用空格隔开
【输出形式】输出开着灯的编号,编号间用空隔隔开
【样例输入】
7 3
【样例输出】
1 5 6 7
【样例说明】K<=n<=1000
#include <stdio.h>
#include "math.h"
int main() {
//n个灯,m个人
int n,m;
int x[10000]={0};
int a=1;
scanf("%d %d",&n,&m);
for (int i = 1; i <= m; ++i) {
for (int j = 1; j <= n; ++j) {
if (j%i==0){
//取反操作
x[j] = !x[j];
}
}
}
for (int i = 1; i <= n; ++i) {
if (x[i] !=0){
if (a) a=0;
printf("%d ",i);
}
}
return 0;
}
开灯问题,这题没怎么理解明白,且网上版本众多,各博主写的也更加详细与理解,这里就不班门弄斧了;
还需要自己理解清楚后在添加解释。
第五题:CCF 201712-1 最小差值
【问题描述】
给定n个数,请找出其中相差(差的绝对值)最小的两个数,输出它们的差值的绝对值。
【输入形式】
输入第一行包含一个整数n。
第二行包含n个正整数,相邻整数之间使用一个空格分隔。
【输出形式】
输出一个整数,表示答案。
【样例输入】
5
1 5 4 8 20
【样例输出】
1
【样例说明】
相差最小的两个数是5和4,它们之间的差值是1。
【样例输入】
5
9 3 6 1 3
【样例输出】
0
【样例说明】
有两个相同的数3,它们之间的差值是0。
【评分标准】
对于所有评测用例,2 ≤ n ≤ 1000,每个给定的整数都是不超过10000的正整数。
#include <stdio.h>
#include "math.h"
int main() {
int n;
int x[1000];
int min;
//数组存储
scanf("%d",&n);
for (int i = 0; i < n; i++) {
scanf("%d",&x[i]);
}
//设第一个差为最小值
min = abs(x[1]-x[0]);
for (int i = 0; i < n; i++) {
for (int j = i+1; j < n; j++) {
//绝对值
if (abs(x[j]-x[i])<min){
min = abs(x[j]-x[i]);
}
}
}
printf("%d",min);
return 0;
}
解释:
该题逻辑与第一题相似,都是假设最小值,然后进行比较,不过这题的最小值是两个差;
原理都是一样,其中点出abs是绝对值的意思;
第一题是通过下标,这题是通过值;
不多解释,不明白可会看第一题解题思路;
第六题:求最大最小数的差
【问题描述】
编程实现如下的功能:取出一个十进制正整数中的所有偶数数字,用这些数字拼成一个最大整数max,取出这个十进制正整数中的所有奇数数字,用这些数字拼成一个最小整数min,计算max和min的差并输出。
【输入形式】输入一行一个十进制整数
【输出形式】输出一行一个符合规定的整数
【样例输入】
74958106
【样例输出】
7061
【样例说明】max为8640,min为1579,差为7061
#include <stdio.h>
#include "math.h"
int main() {
int n;
int x[100];
int k;
scanf("%d",&n);
int num=0;
while (n != 0){
k = n%10;
x[num] = k;
n = (n-k)/10;
num ++;
}
//对列表排序--选择排序
for (int i = 0; i < num-1; ++i) {
int min =i;
for (int j = i+1; j < num; ++j) {
if (x[min]>x[j]){
min=j;
}
}
if (min != i){
int t = x[i];
x[i] = x[min];
x[min] = t;
}
}
//查看数组顺序
// for (int i = 0; i < num; ++i) {
// printf("%d",x[i]);
// }
// printf("\n");
int sum1=1;
int minnum = 0;
int maxnum = 0;
//判断偶数
for (int i = 0; i <num; i++) {
if(x[i]%2 == 0 || x[i]==0){
maxnum+=x[i]*sum1;
sum1 *=10;
}
}
//判断奇数
int sum2=1;
for (int i = num-1; i >=0; i--) {
// printf("%d",i);
if(x[i]%2 != 0){
minnum += x[i]*sum2;
sum2 *=10;
}
}
// printf("%d %d %d",maxnum,minnum,maxnum-minnum);
printf("%d",maxnum-minnum);
return 0;
}
解释:
首先我们需要明确怎么把输入的一串数字化为单个元素保存到数组中;
可以将每个元素(x)使用10取余得到的尾数存到数组中,再/10缩小范围,直到x=0,结束循环;
scanf("%d",&n);
int num=0;
while (n != 0){
k = n%10;
x[num] = k;
n = (n-k)/10;
num ++;
}
然后需要了解数组/列表(python)中的排序问题;
该题在数组排序中我们采用选择排序;
for (int i = 0; i < num-1; ++i) {
int min =i;
for (int j = i+1; j < num; ++j) {
if (x[min]>x[j]){
min=j;
}
}
if (min != i){
int t = x[i];
x[i] = x[min];
x[min] = t;
}
}
数组排序完成后,开始进行奇偶数的判断,将满足条件的元素分别累加乘积;
其中0算在偶数当中;
判断奇数需要翻转数组输出;
//判断偶数
for (int i = 0; i <num; i++) {
if(x[i]%2 == 0 || x[i]==0){
maxnum+=x[i]*sum1;
sum1 *=10;
}
}
//判断奇数
int sum2=1;
for (int i = num-1; i >=0; i--) {
//printf("%d",i);
if(x[i]%2 != 0){
minnum += x[i]*sum2;
sum2 *=10;
}
}
拓展:
选择排序之前python表达的:https://www.cnblogs.com/xbhog/p/11741094.html
总结:
上述题目的解不是唯一,例题中的解是我所理解并运行成功的,如果有不对的地方,欢迎指出。