今天继续分享C语言必会的题目,上一篇文章主要是一些选择题,而今天我们主要内容为编程题的推荐与讲解
准备好迎接下面的题了吗?开始发车了!!!
输入数字 n ,按顺序打印出从 1 到最大的 n 位十进制数。比如输入 3 ,则打印出 1、2、3 一直到最大的 3 位 数 999 。
用返回一个整数列表来代替打印
n 为正整数 OJ链接
OJ链接【牛客网题号: JZ17 打印从1到最大的n位数】
示例: 输入:1 返回值:[1,2,3,4,5,6,7,8,9]
首先我们要对题目进行分析,这里可以理解为n位数中最大的数字,从1开始。实际上是用一个数组来打印这些数字。那我们就得求出一共有多少数字:10^n-1个。比如:1位数10^1 - 1 2位数: 10^2 - 1 3位数: 10^3 - 1。
n在不同情况下不同,如果创建一个能兼容所有的数组会很浪费内存,所以我们使用malloc动态内存开辟解决问题。
注意:是数组下标从0开始,而数值从1开始
int* printNumbers(int n, int* returnSize ) { *returnSize = pow(10, n) - 1; //确定最大的数字 int *arr = (int *)malloc(sizeof(int)*(*returnSize));//申请足够大小的空间 for (int i = 0; i < *returnSize; i++) { arr[i] = i+1;//下标从0开始,而数值从1开始 } return arr; }
根据输入的日期,计算是这一年的第几天。输入保证年份为4位数且日期合法。
输入描述:输入一行,每行空格分割,分别是年,月,日。
输出描述:输出是这一年的第几天
OJ链接【牛客网题号: HJ73 计算日期到天数转换】
这道题简单解法其实将每个月的天数枚举出来,然后根据当前月份向前累加满月的天数,然后再加上当前月所在的 天数。最终考虑平闰年的 2 月份区别是否增加一天。
注意:当二月份没过完时,闰年与平年的判断就没有用,不需要+1或不加,这里得用if进行判断。例如:2000年2月1日 ,虽然是闰年,但是 2月 都没走完那是不能加上闰年多出的一天的。
#include <stdio.h> int is_leap_year(int year) { if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) { return 1; } return 0; } int main() { int a, b, c; int count = 0; int mouth[12] = {31,28,31,30,31,30,31,31,30,31,30,31}; while (scanf("%d %d %d", &a, &b, &c) != EOF) { // 注意 while 处理多个 case for(int i = 0; i < b-1; i++) { count += mouth[i]; } count += c; if(b>2) count += is_leap_year(a); printf("%d\n", count); } return 0; }
判断闰年方法:能被4整除不能被100整除或者能被400整除。
验证尼科彻斯定理,即:任何一个整数 m 的立方都可以写成 m 个连续奇数之和。例如:
1^3=1
2^3=3+5
3^3=7+9+11
4^3=13+15+17+19
输入一个正整数 m(m≤100) ,将 m 的立方写成 m 个连续奇数之和的形式输出。
注意:本题含有多组输入数据。
输入描述:输入一个int整数 输出描述:输出分解后的string
OJ链接【牛客网题号: HJ76 尼科彻斯定理】
示例: 输入:6 输出:31+33+35+37+39+41
看到此题,我们必须在里面找到规律,这样才能快速解题。
首先我们可以看出尼科彻斯定理n是几,后面组成的数就有几个并且全部都是连续奇数。
这时我们就可以遍历求和来得到需要的内容,但是这样的时间复杂度太高,为了优化代码我们继续找其中规律。
能够找到第 n 个数据立方的起始奇数,从这个起始奇数开始,组成连续的n个奇数 项之和的表达式即可。比如: 3^3 的起始奇数是 7 , 则 {7, 9, 11} 3个奇数求和表达式 7 + 9 + 11 。而起始奇数有个规则: m^3 的起始奇数值等于 m * (m - 1) + 1。
能找到起始奇数就非常简单了,只需要再加n-1个奇数即可得到结果。
#include <stdio.h> int main() { int m = 0; while(scanf("%d", &m) != EOF) { int n = m*(m-1)+1; char arr[1000] = {0}; sprintf(arr, "%d", n); for(int i = 1 ; i < m; i++) { sprintf(arr, "%s+%d", arr, n +=2); } printf("%s", arr); } return 0; }
打印时得输出内容的加和,所以我们将其放入字符数组中进行打印。
sprintf:将格式化数据转换成字符串,用法与printf大差不差,只是在参数中多一个转入指针(接收想转入的地址) 。
首先输入要输入的整数个数 n ,然后输入 n 个整数。输出为 n 个整数中负数的个数,和所有正整数的平均值, 结果保留一位小数。
注意: 0 即不是正整数,也不是负数,不计入计算;
本题有多组输入用例。
输入描述:首先输入一个正整数 n ,然后输入 n 个整数。
输出描述:输出负数的个数,和所有正整数的平均值。
OJ链接【牛客网题号: HJ97 记负均正】
示例: 输入: 5
1 2 3 4 5
10
1 2 3 4 5 6 7 8 9 0
输出: 0 3.0 0 5.0
这道题我们最常用的思路使用数组进行操作,但其实我们直接使用scanf捕捉数据即可,统计负数个数,以及正数格式,并且在统计正数个数的过程中求取正数总 和,最后计算得出平均数即可。需要注意的是所有数字中0是不统计在内的。
int main() { int n; while(~scanf("%d", &n)) { int count1 = 0, count2 = 0, tmp; float sum = 0; for (int i = 0; i < n; i++) { scanf("%d", &tmp); if (tmp < 0) { count1++; //统计负数个数 }else if (tmp > 0) { sum += tmp; //正数求和 count2++; //统计大于0的正数个数,这样是因为题目说明0不算在内 } } printf("%d %.1lf\n", count1, sum / count2); } return 0; }
数字总和一定要使用浮点数进行,否则得不到浮点数结果。整数与整数相除得不到浮点数!
小明同学最近开发了一个网站,在用户注册账户的时候,需要设置账户的密码,为了加强账户的安全性,小明对密码强度有一定要求:
1. 密码只能由大写字母,小写字母,数字构成;
2. 密码不能以数字开头;
3. 密码中至少出现大写字母,小写字母和数字这三种字符类型中的两种;
4. 密码长度至少为8
现在小明受到了n个密码,他想请你写程序判断这些密码中哪些是合适的,哪些是不合法的。
输入描述:输入一个数n,接下来有n(n≤100)行,每行一个字符串,表示一个密码,输入保证字符串中只出现大写字母,小写字母和数字,字符串长度不超过100。
输出描述:输入n行,如果密码合法,输出YES,不合法输出NO
示例: 输入:1
CdKfIfsiBgohWsydFYlMVRrGUpMALbmygeXdNpTmWkfyiZIKPtiflcgppuR
输出:YES
OJ链接【牛客网题号: OR141 密码检查】
这道题并不难,但是要求的条件非差多,当我们使用if else语句时,直接将密码遍历一遍进行层层嵌套也可以,但是可读性非常差。所以我们可以直接遍历一遍统计出大小写以及数字的字符个数,通过这些个数进行判断更加方便。
#include <stdio.h> int main() { int n; while(scanf("%d", &n)!=EOF) { for (int i = 0; i < n; i++) { char password[101] = {0}; int upper = 0, lower = 0, digit = 0, other = 0; scanf("%s", password);//捕捉输入的密码 if (strlen(password) < 8) {//密码长度小于8 printf("NO\n"); continue; } if (password[0] >= '0' && password[0] <= '9') {//密码以数字开头 printf("NO\n"); continue; } char *ptr = password; while(*ptr != '\0') { //统计各种字符个数 if (*ptr >= 'a' && *ptr <= 'z') lower++; else if (*ptr >= 'A' && *ptr <= 'Z') upper++; else if (*ptr >= '0' && *ptr <= '9') digit++; else other++; ptr++; } if (other > 0) { // 有其他字符(注意:密码只能由数字和字母组成) printf("NO\n"); continue; } //大写,小写,数字,必须具有两种以上,而比较运算真则1,假则0 if ((upper>0) + (lower>0) + (digit>0) < 2) { // 密码只有一种字符 printf("NO\n"); continue; } printf("YES\n"); } } return 0; }
给你一个整数数组 nums ,其中总是存在 唯一的 一个最大整数 。请你找出数组中的最大元素并检查它是否 至 少是数组中每个其他数字的两倍 。如果是,则返回 最大元素的下标 ,否则返回 -1 。
OJ链接【 leetcode 题号:747. 至少是其他数字两倍的最大数】
示例: 输入:nums = [3,6,1,0] 输出:1
解释:6 是最大的整数,对于数组中的其他整数,6 大于数组中其他元素的两倍。6 的下标是 1 ,所以返回 1 。
输入:nums = [1,2,3,4] 输出:-1
解释:4 没有超过 3 的两倍大,所以返回 -1 。
输入:nums = [1] 输出:0
解释:因为不存在其他数字,所以认为现有数字 1 至少是其他数字的两倍。
方法一:暴力破解,双重循环遍历数组,对每个元素判断是否是其他元素的两倍。或者先遍历一遍找出最大值,然后遍历一 遍判断是否是其他数字二倍。
但是这个方法时间复杂度太高,那哟没有什么更简洁的代码吗?
一次遍历找出最大的数字和次大的数字,判断最大的数字是否是次大数字2倍即可。
int dominantIndex(int* nums, int numsSize){ int max = 0; int a = 0; int lmax = 0; for(int i = 0 ; i < numsSize; i++) { if(nums[i]>max) { max = nums[i]; a = i; } } for(int i = 0 ; i < numsSize; i++) { if(i != a) if(nums[i]>lmax) lmax = nums[i]; } if(max >= 2 * lmax) return a; else return -1; }
时间复杂度为O(n).
给定两个数组,编写一个函数来计算它们的交集。
OJ链接【 leetcode 题号:349. 两个数组的交集】
示例: 输入:
nums1 = [1,2,2,1], nums2 = [2,2]
输出:
[2]
输入:
nums1 = [4,9,5], nums2 = [9,4,9,8,4]
输出:
[9,4]
1 <= nums1.length, nums2.length <= 1000 0 <= nums1[i], nums2[i] <= 1000
暴力破解即可,将 nums1 数组中的每一个数字,判断是否存在于 nums2 数组中,通过这种方式找出交集数据,找出之后判断这个数组是否已经在返回数组中存在,不存在则添加到返回数组中即可。
int* intersection(int* nums1, int nums1Size, int* nums2, int nums2Size, int* returnSize){ static int arr[1000]; *returnSize = 0; int i, j, k; for (i = 0; i < nums1Size; i++) { for (j = 0; j < nums2Size; j++) { if (nums2[j] == nums1[i]) break;//判断nums1[i] 是否在nums2数组中 } if (j == nums2Size) {// nums1中i位置的数据在nums2数组中不存在,则非交集数据 continue; } //只有在另一个数组中存在的数据才能走下来,判断是否已经被添加到返回数组中 for (j = 0; j < *returnSize; j++) { if (nums1[i] == arr[j]) break;//判断nums1[i] 是否在 arr 这个返回数组中 } if (j == *returnSize) {//不在返回数组中,则添加到返回数组中 arr[*returnSize] = nums1[i]; *returnSize += 1; } } return arr; }
给你一个整数数组 nums ,请计算数组的 中心下标 。
数组 中心下标 是数组的一个下标,其左侧所有元素相加的和等于右侧所有元素相加的和。 如果中心下标位于数组最左端,那么左侧数之和视为 0 ,因为在下标的左侧不存在元素。这一点对于中心下标位于 数组最右端同样适用。
如果数组有多个中心下标,应该返回 最靠近左边 的那一个。如果数组不存在中心下标,返回 -1 。
OJ链接【 leetcode 题号:724. 寻找数组的中心下标】
示例: 输入:nums = [1, 7, 3, 6, 5, 6]
输出:3 解释: 中心下标是 3 。 左侧数之和 sum = nums[0] + nums[1] + nums[2] = 1 + 7 + 3 = 11 , 右侧数之和 sum = nums[4] + nums[5] = 5 + 6 = 11 ,二者相等。
输入:nums = [2, 1, -1] 输出:0 解释: 中心下标是 0 。 左侧数之和 sum = 0 ,(下标 0 左侧不存在元素), 右侧数之和 sum = nums[1] + nums[2] = 1 + -1 = 0 。
解题思路:从数组的0下标处开始向后逐下标统计,计算当前下标左边之和,和右边之和,进行判断,相等则为中心下标,如 果数组循环结束都没有找到中心下标,则返回-1,表示没有中心下标。
int pivotIndex(int* nums, int numsSize) { int i, j; for (i = 0; i < numsSize; i++) { int sum_left = 0, sum_right = 0; for (j = 0; j < numsSize; j++) { if (i > j) { sum_left += nums[j]; } else if (i < j) { sum_right += nums[j]; } } if (sum_left == sum_right) { return i; } } return -1; }
Lily上课时使用字母数字图片教小朋友们学习英语单词,每次都需要把这些图片按照大小(ASCII码值从小到 大)排列收好。请大家给Lily帮忙,通过C语言解决。
输入描述:Lily使用的图片包括 "A" 到 "Z" 、 "a" 到 "z" 、 "0" 到 "9" 。输入字母或数字个数不超过 1024 。
输出描述:Lily的所有图片按照从小到大的顺序输出
OJ链接【牛客网题号: HJ34 图片整理】
示例: 输入:
Ihave1nose2hands10fingers
输出:
0112Iaadeeefghhinnnorsssv
这道题就是考察我们如何排序,,每个 ascii 字符在内存都有一个对应的 ascii 值,通过内存中数据的存储进行排序就行。
什么排序方法都行:多种排序方法 有不同排序方法供参考,下面我们使用qsort函数进行排序做题。
#include <stdio.h> #include<string.h> #include<stdlib.h> int compar(const void* p1, const void* p2) { return *(char*)p1 - *(char*)p2; } int main() { char arr[1000]; gets(arr); int sz = strlen(arr); qsort(arr, sz, sizeof(char), compar); printf("%s\n", arr); return 0; }
使用qosrt函数非常简洁方便,不知道如何使用qsort函数,博主之前的博客中有解说:qsort函数使用及模拟
以上是本次推荐的所以内容,感谢大家观看,请多多支持博主。你们的支持是我最大的动力!!!