C语言必会题目(2)

简介: C语言必会题目(2)

今天继续分享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;
}

打印时得输出内容的加和,所以我们将其放入字符数组中进行打印。

68ab62443f5c4b50802a8505cb8acc98.png

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

ca42de92bb6848a9b56773eb84cdd32b.png

暴力破解即可,将 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函数使用及模拟


以上是本次推荐的所以内容,感谢大家观看,请多多支持博主。你们的支持是我最大的动力!!!

目录
相关文章
|
7月前
|
C语言
C语言:数组和指针笔试题解析(包括一些容易混淆的指针题目)
C语言:数组和指针笔试题解析(包括一些容易混淆的指针题目)
|
7月前
|
存储 C语言 C++
C语言------------指针笔试题目深度剖析
C语言------------指针笔试题目深度剖析
47 1
2.C语言题目---字符串左旋
2.C语言题目---字符串左旋
78 1
|
2月前
|
程序员 C语言
【C语言】LeetCode(力扣)上经典题目
【C语言】LeetCode(力扣)上经典题目
|
存储
1.C语言题目---指针类(基础)
1.C语言题目---指针类(基础)
61 1
|
4月前
|
存储 编译器 C语言
【C语言】指针练习题目
【C语言】指针练习题目
|
6月前
|
测试技术 C语言
数据结构学习记录——树习题—Tree Traversals Again(题目描述、输入输出示例、解题思路、解题方法C语言、解析)
数据结构学习记录——树习题—Tree Traversals Again(题目描述、输入输出示例、解题思路、解题方法C语言、解析)
48 1
|
7月前
|
算法 编译器 API
C语言易混淆、简单算法、结构体题目练习、常见关键字总结-1
C语言易混淆、简单算法、结构体题目练习、常见关键字总结
|
6月前
|
C语言
c语言循环题目
c语言循环题目
|
7月前
|
C语言
PTA 浙大版《C语言程序设计(第3版)》题目集 习题8-4 报数 (20分)
PTA 浙大版《C语言程序设计(第3版)》题目集 习题8-4 报数 (20分)