考研C语言程序设计_编程题相关(持续更新)

目录

  • 零、说明
  • 一、程序设计经典编程题(C语言实现)
    • T1 求1~100的奇数
    • T2 求n!
    • T3 求1!+2!+3!+...+10!
    • T4 在一个`有序数组`中查找具体的某个数字n(二分查找)
    • T5 编写代码,演示多个字符从两端移动,向中间汇聚
    • T6 模拟用户登录(三次机会)
    • T7 输入三个数 并从大到小输出
    • T8 打印100~200的素数(质数)
    • T9 打印1000~2000之间的闰年
    • T10 求最大公约数(含递归)
    • 补充:辗转相除法的证明
    • T11 求最小公倍数
    • T12 打印99乘法口诀表
    • T13 不排序 求十个整数中的最大值
    • T14 求1/1-2/1+1/3-4/1.....-100/1
    • T15 计算给定数组中多个数的最大公约数
    • T16 求整数1-100中数字9出现的次数
  • 二、力扣
    • 面试题 17.04. 消失的数字
  • 三、牛客网
    • BC49 判断两个数的大小关系
    • BC84 计算y的值
    • BC101 班级成绩输入输出
    • BC23 时间转换
    • BC50 计算单位阶跃函数
    • BC117 小乐乐走台阶
    • BC112 小乐乐求和(注意数据类型的格式)
    • BC114 小乐乐排电梯(考察细心)

零、说明

  • 第一部分 是平时学习 做真题 做参考书练习 群友提问等等渠道获取到的个人认为比较有价值的题目
  • 第二部分和第三部分 是根据真题+题目热度挑选的题目
  • 本文的难度仅针对普通院校自命题的编程题!
  • 如果一道题确实有两种不同的解法(主要体现在时空复杂度确实有改善 或者思路不一样 比如迭代法和递归法) 本文会分为解法1 解法2进行介绍
  • 一般情况下 最多能写到力扣官方题解的第一或者第二层 大概可以应付考研的编程题 而力扣官方题解更高级的 甚至站在数学角度上去思考 我也无能为力用代码或图片讲述清楚!
  1. 必要的时候我会写题目描述;
  2. 不同的解法思路 我会写上对应的思路+我的错因+我的参考代码 仅供参考
  3. 如果有 还会写本题的总结和一些反思

一、程序设计经典编程题(C语言实现)

T1 求1~100的奇数

解法1 暴力求解:
在这里插入图片描述


解法2: 思考思考 只要知道第一个奇数 后面的+2+2+2不就行了?
在这里插入图片描述


总结:

  1. 解法1 循环一百次 判断一百次
  2. 解法2 循环五十次 不需要判断
  3. 初步领略一下算法的魅力 要多思考
  4. 类似的 下面这道题就可以从3开始打印 每次+3+3+3 而不需要遍历 判断 再打印了
    在这里插入图片描述
  5. 还有一种思路:
    在这里插入图片描述

T2 求n!

  1. 本题很简单 就是累乘
  2. 但是我眼睛瞎起来就把ret定义为0 答案恒为0了

参考代码:

	int n = 5;
	int i = 0;
	int ret = 1;//别写成0了
	for (i = 1; i <= n; i++)
		ret *= i;
	printf("%d\n", ret);

T3 求1!+2!+3!+…+10!

解法1:

  • 思路:两层循环 第一层循环产生1~10的数据 第二层循环求出1! 2! 3!..并累加
  • 注意这种写法 每次求单独求阶乘的时候 ret一定要置为1
    在这里插入图片描述
  • 这种解法不够好 因为有大量的重复计算 将在解法2改进
	int n = 3;//求1! + 2! + 3!
	int i = 0;
	int j = 0;
	int ret = 1;//每次求单独的阶乘的时候就用它
	int sum = 0;
	for (int j = 1; j <= n; j++)
	{
		ret = 1;//所以要记得置为1啊!! 要不然第求下一次阶乘的时候 ret就不是从1开始乘的了
		for (i = 1; i <= j; i++)
			ret *= i;
		sum += ret;
	}
	printf("%d", sum);

解法2:

  • 思路:其实在计算10!的时候 已经出现了1! 2! 3! … 9! 既然如此 就可以一边计算 一边累加 避免了重复计算
  • 解法2更好 是经过思考的
int main()
{
	int n = 10;
	int i = 0;//控制循环
	int ret = 1;//用于产生1! 2! 3!...10!
	int sum = 0;
	for (i = 1; i <= n; i++)
	{
		ret *= i;//在产生10!的过程中 其实已经产生了1! 2! 3!...
		sum += ret;//边乘边加
	}
	printf("%d ", sum);
	return 0;
}

T4 在一个有序数组中查找具体的某个数字n(二分查找)

解法1 直接暴力求解:
在这里插入图片描述


解法2 二分查找:

  1. 前提是:有序 所以不能乱给测试数组
  2. right = mid-1; left = mid+1; 我一开始没有+-1 会导致死循环
  3. int right = len - 1; -1别忘记了 right是下标
  4. 出循环之后有两种写法 可以利用flag 也可以直接判断

写法一:

#include<stdio.h>
int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,11 };//测试数组 一定是有序的
	int len = sizeof(arr) / sizeof(int);//数组元素个数
	
	int k = 11;//查找目标
	int flag = 0;//假设一开始默认找不到k 找到了就把第flag置为1
	
	int left = 0;
	int right = len - 1;
	int mid = 0;
	// = 也是可以取的 当left=right的时候 肯定还要进去判断一次
	while (left <= right)
	{
		//每次进循环 都要算出一个新的mid进行判断
		mid = (left + right) / 2;
		if (arr[mid] < k)
		//说明k在mid的右边
		{
			left = mid + 1;
		}
		else if (arr[mid] > k)
		//说明k在mid的左边
		{
			right = mid - 1;
		}
		else
		{
			//这里已经可以输出mid的信息了 但是我放在下面打印
			//把提示信息统一都放在循环外处理
			flag = 1;
			break;
		}
	}
	//程序执行到这 有两种可能
	//1.while全都判断完 自然结束 也就是最终没找到k 此时flag = 0
	//2.flag = 1之后 break到这里来
	if (flag)
		printf("找到了下标是:%d\n", mid);
	else
		printf("没找到");
	return 0;
}

写法二: 主要差异在于出循环之后 我怎么输入"没找到"比较合适

int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10};
	int num = 0;
	while (2)
	{
		printf("输入你要查到的数字:\n");
		scanf("%d", &num);
		int left = 0;
		int right = (sizeof(arr) / sizeof(int))-1;
		int mid = 0;
		while (left <= right)
		{
			mid = (left + right) / 2;
			if (arr[mid] > num)
				right = mid-1;
			else if (arr[mid] < num)
				left = mid+1;
			else
			{
				printf("找到了 下标是%d\n", mid);
				break;
			}
		}
		//走到这里 有两种情况 1.找到了break出来 2.没找到 但是left不<=right 循环结束了
		//我直接判断一下此时mid对应的元素是不是num就能确定找没找到了 不需要flag也行
		if (arr[mid] != num)
			printf("没找到\n");
	}

	return 0;
}

T5 编写代码,演示多个字符从两端移动,向中间汇聚

题目描述:
打印hello world!
############
h##########!
he########d!
hel######ld!
hell###r#ld!
hello##orld!
hello world!


解法1:

  1. 双"指针" 一左一右 开始打印有效字符
  2. 每次肯定都是打印十个字符 打印几次由while来决定
  3. left和right把10个要打印的字符分成三部分 [0,left]打印对应的有效字符 [right,len-1]打印对应的有效字符 剩余部分打印#
  4. 相较于思路2 更节省空间

错因:

  1. 打印#的判断条件写错了 左右不分??!! 开区间(left,right)范围打印#
  2. 每一次for循环结束 不要忘记++和-- 也不要忘记换行
#include<stdio.h>
#include<windows.h>
#include<string.h>
int main()
{
	char ch[] = "hello world!";
	int len = strlen(ch);//12
	int left = 0;
	int right = len - 1;
	int i = 0;

	while (left<=right)
	{
		for (i = 0; i < len; i++)
		{
			if (i > left && i < right) //易错
				printf("#");
			else
				printf("%c", ch[i]);
		}
		printf("\n");
		Sleep(1000);
		left++;
		right--;
	}
	return 0;
}

解法2:

  1. 给出两个数组 一个是字符 一个是# 注意#和字符的个数肯定都是一样的
  2. 然后也是用了两个指针 一左一右依次把字符赋给放#的那个数组
  3. 打印的时候 用%s专门只打印#的那个数组即可

错因:

  1. len–>求的是元素个数 也就是字符个数 故下标最大值是len-1
  2. 判断部分是<= 当左右指针指向同一个元素的时候 也要进入循环的
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<windows.h>
#include<string.h>
int main()
{
	char ch1[] = "zhuchenyang66dds6!";
	char ch2[] = "******************";
	int len = strlen(ch1);
	int left = 0;
	int right = len - 1;
	for (left = 0, right = len - 1; left <= right; left++, right--)
	{
		ch2[left] = ch1[left];
		ch2[right] = ch1[right];
		printf("%s\n", ch2);
		Sleep(100);
	}
	return 0;
}

或者写成while循环 都是一样
Sleep()的头文件是windows.h
system()的头文件是stdlib.h
在这里插入图片描述

T6 模拟用户登录(三次机会)

题目描述:
编写代码实现,模拟用户登录情景,并且只能登录三次。(只允许输入三次密码,如果密码则提示登录成,如果三次均输入错误,则退出程序。


解法1 利用strcmp函数:

  1. 定义要输入的密码 正确密码 count是还剩下几次机会
  2. 只要count还没==0 就可以进去输入密码

我的错因:

  1. 一开始用的是下图这种定义方式 这样定义的话 其实数组大小是确定的 数组里放了一个空格 一个\n 元素个数(strlen)是1 大小(sizeof)是2字节 下面输入密码肯定会越界的

在这里插入图片描述
2. 比较字符串是否相等 不能用== 要用strcmp()函数 第一个参数比第二个参数大 就返回>0 相等的话返回0
在这里插入图片描述

#include<stdio.h>
#include<string.h>
int main()
{
	char pswd[100] = " ";
	char answer[100] = "zhukefu123";
	int count = 3;

	while (count>0)
	{
		printf("您还有%d次机会,请输入密码:\n",count);
		scanf("%s", pswd);
		if (strcmp(pswd, answer) != 0)
		{
			printf("密码错误!\n");
			count--;
			continue;
		}
		else
		{
			printf("密码正确!\n");
			break;
		}
	}
	if (count == 0)
		printf("您没有机会了!!\n");
	return 0;
}

解法2 直接暴力求解 相当于模拟实现了strcmp:

  1. 这里我犯了一个离谱的错误 多打了一个; 也就是这个if 啥也不干! 然后继续往下执行!
    在这里插入图片描述
  2. 下图这部分写错了 左闭右开的话 右边就是循环次数 也就是字符串长度 是不需要-1的 -1会导致少判断最后一个字符 也就是zcygst667也被算成密码正确了
    在这里插入图片描述
  3. char ch[10] = " "; 10给的太小了!!! 要么限定用户只能输入多少的字符(一般交给前端限制) 要么给大点 否则 如果我测试的时候输入了一个zcysdshjadhshkd 会有栈溢出err
  4. 这个错误算是值得注意的点 我要是用flag这种写法的话 每次给你一次新机会输入密码的时候 flag都应该重置为1!!!! 否则在以下情况会出现问题: 当我第一次输入zcygst667 进入for的时候 把flag置为0 如果我后面输入了正确密码zcygst666 虽然不会执行flag=0 但是for循环出来走到if (flag == 1)的时候 发现flag上次已经给他置为0了 所以不进入if 直接继续下一次循环了 仿佛跳过了这次正确的输入
  5. 主要就三个点的错误(下图已经修正)
    在这里插入图片描述
int main()
{
	int total = 8;
	int i = 0;
	char ch[1000];
	char real[1000] = "zcygst666";
	int flag = 1;
	while (total > 0)
	{
		flag = 1;
		scanf("%s", ch);
		if (strlen(real) == strlen(ch))
		{
			for (i = 0; i < strlen(ch); i++)
			{
				if (ch[i] != real[i])
				{
					printf("错误\n");
					total--;
					flag = 0;
					printf("还剩%d次机会\n", total);
					break;
				}
			}
			//程序走到这这里 
			//1.break出来的  flag已经是0
			//2.判断发现全相等 循环自然结束 flag仍然是1
			if (flag == 1)
			{
				printf("正确\n");
				break;
			}
		}
		else
		{
			printf("两个字符串长度都不一样!!错误\n");
			total--;
			printf("还剩%d次机会\n", total);
		}
	}
	
	return 0;
}


  • 其实我想说的是 针对解法2那个flag置为1的错误 还是要具体问题具体分析的 具体看自己的思路是什么 灵活编写代码
  • 比如下面的代码(一开始给flag初始化的是0 密码正确再改为1) 就不需要每次都置为1 所以要多写多练多反思 该置为1的时候 我自己心里有数就行
int main()
{
	int i = 10;
	char real[20] = "zcygst";
	char input[20];
	int flag = 0;
	while (i > 0)
	{
		scanf("%s", input);
		if (strcmp(real, input) != 0)
		{
            //密码错误 那就不要动flag 本身就是0!
			i--;
			printf("err还剩%d次机会\n", i);
		}
		else
		{
            //输对了才改为1
            flag = 1;
			printf("yes\n");
			break;
		}
	}
    //1.要么是break到这里的时候 此时flag为1
    //2.要么就是一次都没输对 不满足i>0跳到这里来 此时flag一直保持是0
	if (flag == 0)
		printf("你没机会了\n");
	return 0;
}

T7 输入三个数 并从大到小输出

思路:
确定三个数了 用排序似乎有点小题大做了
其实比较三次即可 保证a放的最大 c放的最小 然后打印abc即可
而且三次比较都要交换 不如封装成一个函数 但是注意这个函数就必须要传地址了

#include<stdio.h>

void swap(int* x,int* y)
{
	int tmp = *x;
	*x = *y;
	*y = tmp;
}

int main()
{
	int a = 1;
	int b = 1;
	int c = 1;
	printf("请输入三个数:>\n");
	scanf("%d %d %d", &a, &b, &c);
	//目标:让a里放最大 b其次 c最小
	//前两个if可以保证a最大 第三个if让c最小
	if (a < b)
		swap(&a, &b);
	if (a < c)
		swap(&a, &c);
	if (c > b)
		swap(&b, &c);
	//从大到小输出
	printf("%d %d %d", a, b, c);

	return 0;
}

T8 打印100~200的素数(质数)

思路:

  1. 素数只能被1和本身整除 如果能找到一个非1非本身的因数 就可以判断不是素数
  2. 判断i是不是素数的时候 可以从闭区间[2,i-1]试除
  3. 优化1:只要试除[2,根号i] 比如16 如果有因数 一定是成对出现的 比如1-16 2-8 4-4 如果只看一半的话 肯定是不会大于根号16的(≤)
  4. 优化2:偶数肯定不是素数 直接从101开始 每次i+2 从奇数里面找素数
    在这里插入图片描述
  5. double sqrt (double x);需要math.h的头文件 不放心的话循环里也可以强转成int
  6. 以上的方法 都叫"试除法" 推荐博文:<<素数求解的N种境界>>
#include<stdio.h>
#include<math.h>
int main()
{
	int i = 0;
	int j = 0;
	int flag = 1;
	//产生100-200的素数
	for (i = 100; i <= 200; i++)
	{
		//每次产生的i 开始都先认为他是个素数
		flag = 1;
		//这里是<=啊 写<的话 49也被判断成素数了
		for (j = 2; j <= (int)sqrt(i); j++)
		{
			if (i % j == 0)
			{
				flag = 0;//那就不是素数
				break;//只要有一次能进来 就直接break了
			}
		}
		//走到这儿来 可能是
		//1.break到这儿来 此时flag=0 
		//2.循环条件结束 此时flag仍未1 也就是i%j一次都不等于0 没机会把flag置为0 说明是素数
		if (flag)
			printf("%d ", i);
	}
	return 0;
}

T9 打印1000~2000之间的闰年

1. 能被4整除 但是不能被100整除的 是闰年
2. 能被400整除 也是闰年
3. 其实可以i+=4 从1.2.的规则来看 闰年肯定能被4整除

	int i = 0;
	for (i = 1000; i <= 2000; i++)
	{
		if ((i % 400 == 0) || ((i % 4 == 0) && (i % 100 != 0)))
			printf("%d ", i);
	}

注意了 如果要用if来写的话
就是俩个if(并列关系 都需要判断的)
而不能是else if(非此即彼 只有一个入口)
如果写的是else if 2000本身是闰年 但是判断他不是 因为只能进去第一个if
在这里插入图片描述

T10 求最大公约数(含递归)

解法1:暴力求解
两个数的最大公约数的范围肯定是[1,较小值]
比如18和6 最大公约数不可能超过6 所以从1到6找就行

	int m = 18;
	int n = 24;
	//假设m和n的较小值为最大公约数
	int min = m > n ? n : m;
	//然后从较小值开始 往下试除
	int i = 0;
	for ( i = min; i >= 1; i--)
	{
		if ((m % i == 0) && (n % i == 0))
			break;
	}
	printf("%d", i);
  • 下图是while的写法
    在这里插入图片描述

解法2:辗转相除法:
主要用到的一个结论就是:(a,b)的最大公约数等于(b,a%b)的最大公约数
最大公约数:即两个数据中公共约数的最大者。
思路:
例子:18和24的最大公约数
第一次:a = 18 b = 24 c = a%b = 18%24 = 18 再使:a = 24 b=18
第二次:a = 24 b = 18 c = a%b = 24%18 = 6 再使:a = 18 b = 6
第三次:a = 18 b = 6 c=a%b = 18%6 = 0 循环结束 此时的b就是最大公约数
下面有两种不同的风格写法 建议写第二种

int main()
{
	int m = 18;
	int n = 24;
	int k = m % n;
	while (k != 0)
	{
		m = n;
		n = k;
		k = m % n;
	}
	printf("%d", n);
	return 0;
}
int main()
{
	int a = 18;
	int b = 24;
	int c = 0;
	//当某一次 c = a%b = 0  为假了 就不进去循环了 此时b就是最大公约数
	while(c=a%b)
	{
		a = b;
		b = c;
	}
	printf("%d\n", b);
	return 0;
}


解法3:递归法
可以看出 求18 24->求24 18->求18 6(递归的出口)
递归的关键在于能否找到子问题

#include<stdio.h>

void IsCommon(int a, int b)
{
	if (a % b == 0)
	{
		printf("最大公约数是%d ", b);
		return;
	}
	else
		IsCommon(b, a % b);
}

int main()
{
	int a;
	int b;
	
	while (1)
	{
		scanf("%d %d", &a, &b);
		IsCommon(a, b);
	}

}

补充:辗转相除法的证明

详细的证明过程可以参考:
辗转相除法原理

注意除了参考视频里的两个结论,具体实现证明还需要引入一个公理:整数a,b的最大公约数d1一定大于or等于整数a,b,c的最大公约数d2的(当c有一个约数恰好是d1时取等号)
在这里插入图片描述

T11 求最小公倍数

设两数的最大公因数=X
则:两数可以表示为:aX,bX(a,b一定互质)
所以aX,bX的最小公倍数=abX=(aX*bX)/X
即最小公倍数=两数之积/最大公约数

那么也可以进一步
证明出两个数的乘积 = 最大公因数与最小公倍数的乘积
aX*bX = X*(abX)=(aX)*(bX)

代码思路:
暴力求解的话和前面类似 不过这次是拿两者较大的值开始试
比如6和8的最小公倍数 就用[8,6*8]的范围试
或者先求出最大公约数 然后最小公倍数就 = 两数之积/最大公约数
注意:如果用int,最小公倍数可能会溢出 建议结果用long long保存

T12 打印99乘法口诀表

就提几个注意点:

  1. %数字d 不要写成数字%d
  2. -2是左对齐两位(就记成按照我平时的习惯 就喜欢写-2左对齐) 2是右对齐两位
  3. 不要乱用对齐 这里前两位乘数就不可能有两位 不需要对齐 只有结果可能是两位 在这里插入图片描述

这就是 %2d的样子 是右对齐
在这里插入图片描述

int main()
{
	for (int i = 1; i <= 9; i++)
	{
		for (int j = 1; j <= i; j++)
		{
			printf("%d*%d=%d ", i, j, i * j);
		}
		printf("\n");
	}
	return 0;
}

T13 不排序 求十个整数中的最大值

思路:

  1. 定义一个数组 放10个整数
  2. 假设第一个元素是最大值max
  3. 然后循环 让max和第二个开始的元素一一比较 如果遇到比max大的就重新赋值给max

错因:

  • max应定义为arr[0] 而不是一个具体的数 比如max=0 如果arr都是负数呢?
  • 在数组里挑一个最大的 肯定是以数组里元素的为标杆 不能随便找一个标杆 在我们班找一个最能打的 能找泰森作为标杆吗?
  • 如果是自己输入的数据 那max一定要等输入完再定义为arr[0]
    在这里插入图片描述

T14 求1/1-2/1+1/3-4/1…-100/1

思路:
虽然下面两种想法代码写出来一模一样 但是思考方式不一样

  1. 分子恒为1 产生正负交替的分母 累加即可:sum += 1.0 / (i*symbl);
  2. 分子恒为1 分母每次递增1 让整体的计算结果正负交替:sum += symbol * (1.0 / i);
    在这里插入图片描述
  • 注意:1.0默认是double 计算出来的sum也就是double
    如果定义的是float double->float会报警告 最好double sum 然后用%lf打印
    在这里插入图片描述

思路很多 还可以分两部分计算
奇数项是+ 偶数项是-
在这里插入图片描述

T15 计算给定数组中多个数的最大公约数

问题描述:
前面只会求两个数的最大公约数 那怎么求一组数的最大公约数呢?


思路:
M=aX N=bX 且ab互质 则gcd(M,N)=X
若再gcd(X,K)=z
则gcd(M,N,K)=z

在这里插入图片描述

第1次循环:求gcd(0,1) result放的是 0和1的最大公约数
第2次循环:求gcd(0和1的最大公约数,2) result放的是 0和1和2的最大公约数
第3次循环:求gcd(0和1和2的最大公约数,3) result放的是 0和1和2和3的最大公约数

int gcd(int m, int n)
{
	int c = 0;
	//当某一次 c = a%b = 0  为假了 就不进去循环了 此时b就是最大公约数
	while (c = m % n)
	{
		m = n;
		n = c;
	}
	return n;
}

int main()
{
    int arr3[] = { 26, 39, 52, 65, 78, 91 };
    //用于存放结果
    int result = arr3[0];

    for (int i = 1; i < 6; i++)
    {
        result = gcd(result, arr3[i]);
    }

    printf("%d ", result); // 输出最大公约数
    return 0;
}

这是我写的代码
看似利用了数组 循环次数也少了 但属实没必要呀!
微不足道的提升 而且不如前面的代码好理解!!
除非他题目真的要求 不准新建变量 倒确实可以这么写
自己画图看看的话 其实两个代码的思路是完全一样的 前面的思路更清晰!!!
在这里插入图片描述

T16 求整数1-100中数字9出现的次数

错因:
下面的错误在于 个位和十位 都要被判断到
假如是99 进去第一个if 判断个位是9 ++之后 就不会进入else if了
直接开始判断100 少判断了一个99的十位9
if elseif else 是一个整体 只有一个入口
而这道题就是要每一位都作为一个入口 每一位都要判断一下
在这里插入图片描述
写||也不对 99还是只判断了一次
在这里插入图片描述

两种情况都需要判断的情况 不能用if elseif
if - if 符合要求 个位要判断一下 十位也要判断一下:

int main()
{
	int count = 0;
	for (int i = 1; i <= 100; i++)
	{
		if (i / 10 == 9)
			count++;
		if (i % 10 == 9)
			count++;
	}
	printf("%d", count);
	return 0;
}

二、力扣

面试题 17.04. 消失的数字

题目链接

  1. 解法一:首先^遵循交换律 且0^N=N N^N=0 把所有的元素都^起来 相同的都成0 剩下一个单独的 就是消失的数字 相当于找单身狗
  2. 解法二:既然题目描述里的n 其实应该等于numsSize 也就是我应该有的元素是0,1,2,3,4,n(numsSize) 把他们全都加起来去减数组的值 结果就是那个孤儿
  3. 解法二还可以优化 1-n求和直接用公式 都不需要遍历
//我的代码:
int missingNumber(int* nums, int numsSize) {
    int ret = 0;
    int sum = 0;
    for (int i = 0; i < numsSize; i++) {
        scanf("%d", &nums[i]);
        ret = ret ^ nums[i];
        ret = ret ^ i;
    }
    ret = ret ^ numsSize;

    //思路二:
    // for (int i = 0; i <= numsSize; i++) {
    //     sum += i;
    // }

    // for (int i = 0; i < numsSize; i++) {
    //     scanf("%d", &nums[i]);
    //     sum -= nums[i];
    // }
    return ret;
}

三、牛客网

BC49 判断两个数的大小关系

题目链接

  • 这题很简单 主要是学习一下牛客网多组输入的写法
  • 读取失败返回EOF 如果不是EOF那肯定读取成功
#include<stdio.h>
int main() {
    int n1 = 0;
    int n2 = 0;
    while (scanf("%d %d", &n1, &n2) == 2) {
        if (n1 == n2)
            printf("%d=%d\n", n1, n2);
        else if (n1 > n2)
            printf("%d>%d\n", n1, n2);
        else
            printf("%d<%d\n", n1, n2);
    }
    return 0;
}

循环条件也可以写成:while (scanf("%d %d", &n1, &n2) != EOF)

BC84 计算y的值

题目链接

  • 那么有的朋友就要问了 这么简单的题放进来侮辱我的智商? 举报点踩拉黑了

  • 主要还是因为我第一次写的时候居然写了2个if1个else 一般是讨论单值函数的! 只有一个入口!
    在这里插入图片描述

  • 正确:x和y是一一映射关系 只有一个入口

#include <stdio.h>

int main() {
    int x;
    int y;
    while (scanf("%d", &x) != EOF) {
        if (x < 0)
            y = 1;
        else if (x == 0)
            y = 0;
        else
            y = -1;
        printf("%d\n",y);
    }
    return 0; 
}

BC101 班级成绩输入输出

题目链接

  • 注意点1:每次循环求和之前 sum置为0不要忘记了 否则第一位同学是对的 第二位同学的总分 是接着上一位的sum继续算的
  • 注意点2:下面如果写scanf(“%f”,&score); 就是错的 读取到的都是0
  • 对于scanf来说 double->%lf; float->%f
  • 对于printf来说 浮点数double和float都用%f是没问题的
  • 注意点3:看清题目 明明是保留1位小数了!! %.1f
    我写的参考答案:
    还是稍微有点投机取巧的 因为这是OJ 一边输入 一边输出 一边求和
#include<stdio.h>
int main()
{
    double score;
    double sum = 0;
    for(int i = 0;i<5;i++)
    {
        sum = 0;
        for(int j = 0;j<5;j++)
        {
            scanf("%lf",&score);
            printf("%.1f ",score);
            sum+=score;
        }
        printf("%f",sum);
        printf("%c",'\n');
    }
    return 0;
}

弄一个数组逻辑上更好:
下面这个代码还有错 输出那部分的while忘记给j++了 死循环了
在这里插入图片描述

BC23 时间转换

题目链接
思路1:分别算时分秒

  • 注意是3661s一共是几小时几分钟几秒 而不是分别转换成时分秒
  • 小时:3661/3600 看看里面有几个3600s 也就是几个h
  • 分钟:3661/60 看看里面有几个60s 也就是几分钟 再%60 因为满60分钟就要进位给h了 剩下的就是不满60分钟不能进位的 也就是分钟数
  • 秒:其实很简单 直接%60 或者/1%60 逻辑更统一 先看看有多少个1s 然后再%60 因为满60s就要进位给分钟了 剩下的就是秒数部分
#include <stdio.h>
int main() {
    int seconds = 0;
    scanf("%d", &seconds);
    printf("%d %d %d", 
    seconds / 3600, 
    seconds / 60 % 60, 
    seconds % 60);
    return 0;
}
#include <stdio.h>
int main() {
    int a;
   while (scanf("%d", &a) != EOF) {
       printf("%d %d %d", a / 3600, a / 60 % 60, a / 1 % 60);
   }
   return 0;
}

思路2:连着算

  • 一开始算小时数肯定都一样 区别在于后面算分秒的时候 是接着上次的结果算的
  • 3661%3600 就把能凑成1h的秒数都去掉了 剩下的秒数/60就是分钟数部分 %60就是秒数部分
  • 认为思路二更清晰
    在这里插入图片描述

BC50 计算单位阶跃函数

题目链接

  • 这波没有侮辱智商 而是突然发现printf里可以直接打印字符串 总感觉以前都没注意到过
  • 可参考C语言复习第0章 4.7
    在这里插入图片描述

BC117 小乐乐走台阶

题目链接

本题在C语言专栏里的:C语言函数递归经典例题:汉诺塔和小青蛙跳台阶已经详细介绍过
这里主要再提供一种思考方式

  • 常见的思路就是跳n级 分为第一次跳1级和第一次跳2级
    在这里插入图片描述

  • 或者可以这么想:当我跳到了第n级 我可能是从第n-1级跳上来的 也可能是从n-2级跳上来的
  • 那么跳到第n级的所有跳法就是:跳到第n-1级的所有跳法+跳到第n-2级的所有跳法
  • 继续往下递推 可以一直推到:跳到第3级的所有跳法就是 跳到第2级的所有跳法+跳到第1级的所有跳法(已知)
  • 只是思路不一样 其实写出来的代码都是一模一样的

则代码思路:

  1. 定义Search(n)是搜索跳n个台阶 有多少种跳法
  2. 子问题Search (n-1)+Search(n-2)
  3. 出口是:n==1 n==2
#include <stdio.h>

int Search(a) {
    if ((a == 1) || (a == 2))
        return a;
    else
        return Search(a - 1) + Search(a - 2);
}

int main() {
    int a;
    while (scanf("%d", &a) != EOF) { 
        int ret = Search(a);
        printf("%d", ret);
    }
    return 0;
}

BC112 小乐乐求和(注意数据类型的格式)

题目链接

错因:
这题很简单 用累加或者求和公式都可以
就是要注意题目描述:输入一个正整数n (1 ≤ n ≤ 109) 这个数很大
求完和肯定超过int的范围了 所以要用足够大的整型 这里直接给long long
但是还是要注意:给了long long scanf和printf都要是%lld 在这里插入图片描述

补充:
在C语言里 用/2总是会很担心的 因为有可能是整数/ 可能不是我们想象中的除法
那么这题为什么可以直接/2呢?
也就是说 分子一定是偶数?
等差数列Sn = (a1+an)*n/2 = n*[2a1+(n-1)d]/2
即证n*[2a1+(n-1)d]是偶数
1.如果n是偶数 显然成立
2.如果n是奇数 n-1肯定是偶数 (n-1)d肯定是偶数 2a1+(n-1)d肯定还是偶数 显然也成立
在这里插入图片描述

BC114 小乐乐排电梯(考察细心)

题目链接

  • 这题一点也不难 完全就是考察细不细心的 是到楼上 不是等几分钟能坐上电梯
    在这里插入图片描述
    在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/893228.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Ubuntu】在Ubuntu上安装IDEA

【Ubuntu】在Ubuntu上安装IDEA 零、前言 最近换了Ubuntu系统&#xff0c;但是还得是要写代码&#xff0c;这样就不可避免地用到IDEA&#xff0c;接下来介绍一下如何在Ubuntu上安装IDEA。 壹、下载 这一步应该很容易的&#xff0c;直接打开IDEA的下载页面&#xff0c;点击下…

精密仪器制造企业如何保障安全高效的跨网文件交换?

在数字化时代&#xff0c;精密仪器制造企业面临着日益增长的跨网文件交换需求。这些企业通常拥有多个隔离的网络环境&#xff0c;如内网、外网、测试网等&#xff0c;以确保数据安全和合规性。然而&#xff0c;如何在保障数据安全的同时&#xff0c;实现文件的快速、稳定传输&a…

前端学习-css的元素显示模式(十五)

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 目录 前言 什么是元素显示模式 块元素 常见的块元素 块元素的特点 注意 行内元素 行内元素的特点 注意 行内块元素 行内块元素的特点 元素显示模式的转换 语法格…

黑马程序员-redis项目实践笔记1

目录 一、 基于Session实现登录 发送验证码 验证用户输入验证码 校验登录状态 Redis代替Session登录 发送验证码修改 验证用户输入验证码 登录拦截器的优化 二、 商铺查询缓存 缓存更新策略 数据库和缓存不一致解决方案 缓存更新策略的最佳实践方案 实现商铺缓…

【UML】一个UML学习的还不错的几个帖子

https://segmentfault.com/a/1190000042775634 寂然解读设计模式 - UML类图&类的六大关系-阿里云开发者社区

学习threejs,网格深度材质MeshDepthMaterial

&#x1f468;‍⚕️ 主页&#xff1a; gis分享者 &#x1f468;‍⚕️ 感谢各位大佬 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍⚕️ 收录于专栏&#xff1a;threejs gis工程师 文章目录 一、&#x1f340;前言1.1 ☘️网格深度材质MeshDepthMate…

【数据结构与算法】栈和队列

文章目录 一.栈1.1定义 顺序栈和链式栈1.2基本操作1.2.1表示1.2.2初始化1.2.3清空1.2.4销毁1.2.5入栈1.2.6出栈1.2.7取栈顶 1.3共享栈1.3.1定义1.3.2进栈出栈 二.队列2.1定义 顺序队列和链式队列循环队列2.2基本操作2.2.1初始化2.2.2判空2.2.3求队列长度2.2.4取队头元素2.2.5销…

Spring 的依赖注入的最常见方式

在 Spring 中&#xff0c;依赖注入的方式有多种选择。下面我们来逐一分析它们的特点、适用场景和注意事项&#xff1a; 1. 构造函数注入 构造函数注入要求在对象创建时提供所有依赖。这种方式确保依赖在对象创建后不可变&#xff0c;特别适合必须强制存在的依赖。所有依赖在对…

我谈Sobel算子与高斯一阶微分的关系

现在算力提升了&#xff0c;最常用的一阶差分边缘检测算子已经不是Sobel算子了&#xff0c;而是高斯一阶微分。 高斯一阶微分 顾名思义&#xff0c;高斯函数的一阶导数。 Derivative of Gaussian 1D 一维直接扩展到二维。 禹晶、肖创柏、廖庆敏《数字图像处理&#xff08;面…

【python爬虫】携程旅行景点游客数据分析与可视化

一.选题背景 随着旅游业的快速发展&#xff0c;越来越多的人选择通过互联网平台预订旅行产品&#xff0c;其中携程网作为国内领先的在线旅行服务提供商&#xff0c;拥有大量的旅游产品和用户数据。利用爬虫技术可以获取携程网上各个景点的游客数据&#xff0c;包括游客数量、游…

3D Slicer 教程二 ---- 数据集

上一章下载3d slicer的软件,这章从加载数据集来弄清楚3dslicer怎么使用. 一. 加载数据集 如果没有数据集,也可用用样本数据. (1) "File" --> "add Data" 可以添加图片文件夹,(试了MP4不行,内镜的视频估计不支持),添加单个图片的话,会出现一些选项, …

【C++11】可变模板参数详解

个人主页&#xff1a;chian-ocean 文章专栏 C 可变模板参数详解 1. 引言 C模板是现代C编程中一个非常强大且灵活的工具。在C11标准中&#xff0c;引入了可变模板参数&#xff08;variadic templates&#xff09;&#xff0c;它为模板编程带来了革命性改变。它的出现允许我们…

四、Spring Boot集成Spring Security之认证流程

一、Spring Boot集成Spring Security专栏 一、Spring Boot集成Spring Security之自动装配 二、Spring Boot集成Spring Security之实现原理 三、Spring Boot集成Spring Security之过滤器链详解 四、Spring Boot集成Spring Security之认证流程 五、Spring Boot集成Spring Se…

锥线性规划【分布鲁棒、两阶段鲁棒方向知识点】

1 锥线性对偶理论 本部分看似和分布鲁棒、两阶段鲁棒优化没什么关系&#xff0c;但值得优先学习&#xff0c;原因将在最后揭晓。 二阶锥 二阶锥&#xff08;second-order cone&#xff0c;又称ice-cream/Lorentz cone&#xff09;的形式为&#xff1a; 非负象限锥 半正定锥 …

【工具变量】上市公司企业广告支出数据(2007-2023年)

一、测算方式&#xff1a;具体而言&#xff0c;参照 Lu 等&#xff08;2022&#xff09;的研究&#xff0c;本文通过上市公司财务报表附注获取每家上市公司每年销售费用明细项目&#xff0c;筛选出广告费、广告宣传费、广告推广费、广告策划费、广告展览费等与广告支出相关的项…

【Git】基本操作+分支管理

Git基本操作 Git仓库创建 Git仓库的基本认知 Git仓库就是一个用来跟踪和管理项目文件变化的地方&#xff0c;其记录了所有的修改历史&#xff0c;可以回退到之前的任何一个历史版本 工作区&#xff1a;正在进行实际操作的文件夹暂存区&#xff1a;临时保存想要提交修改的区域…

美国处方利用数据库查询方法

众所周知&#xff0c;药物的处方利用数据一直是评估药品市场渗透率、患者用药习惯以及药品普及程度的重要依据&#xff0c;也是监管机构评估医疗补助计划效率和效果的重要指标&#xff0c;而对于医药企业而言&#xff0c;了解药物的处方利用情况&#xff0c;可以助力他们更好对…

tensorflow入门案例手写数字识别人工智能界的helloworld项目落地1

参考 https://tensorflow.google.cn/?hlzh-cn https://tensorflow.google.cn/tutorials/keras/classification?hlzh-cn 项目资源 https://download.csdn.net/download/AnalogElectronic/89872174 文章目录 一、案例学习1、导入测试和训练数据集&#xff0c;定义模型&#xff…

树莓派应用--AI项目实战篇来啦-13.OpenCV摄像头云台人脸追踪

1. OpenCV 舵机云台人脸追踪介绍 本项目内容和前面学习的云台追踪物体是一样的原理&#xff0c;只是这里把追踪物体修改成追踪人脸&#xff0c;在前面的内容中&#xff0c;我们已经学习了二维云台的物体追踪&#xff0c;理解了二维云台对物体追踪的PID控制模型&#xff0c;在本…

vue+leaflet示例:克里金插值渲染显示(附源码下载)

demo源码运行环境以及配置 运行环境&#xff1a;依赖Node安装环境&#xff0c;demo本地Node版本:14.19.1。运行工具&#xff1a;vscode或者其他工具。配置方式&#xff1a;下载demo源码&#xff0c;vscode打开&#xff0c;然后顺序执行以下命令&#xff1a; (1)下载demo环境依赖…