写点什么

第四章 C 语言之牛客网刷题📖笔记

作者:Dream-Y.ocean
  • 2022 年 9 月 16 日
    广东
  • 本文字数:5843 字

    阅读完需:约 19 分钟

第四章 C语言之牛客网刷题📖笔记




作者介绍:


:mortar_board:作者:热爱编程不起眼的小人物:goat::mag_right:作者的 Gitee:代码仓库:pushpin:系列文章推荐:

1.【第一章】 C语言之牛客网刷题笔记 【点进来保证让知识充实你一整天】2.【第二章】 C语言之牛客网刷题笔记 【点进来保证让知识充实你一整天】3.【第三章】 C语言之牛客网刷题笔记 【点进来保证让知识充实你一整天】:ledger:我和大家一样都是初次踏入这个美妙的“元”宇宙:earth_asia: 希望在输出知识的同时,也能与大家共同进步、无限进步:star2:


🌐为大家推荐一款刷题网站呀👉点击跳转以下题目 &算法思想,都可以从此网站中找到并参考学习哟~




@TOC



前言

同学们,新的学期早已开始啦:kissing_closed_eyes:~相信大家都想在这学期偷偷地卷”死“同学吧:innocent:大学里里可以做的事情有很多哦,我们一定要好好地利用好这段时间,努力地提升自己,大胆放手一搏吧!:fist:

星光不负赶路人,时光不有心人


只要我们以深深地谦卑去忍耐 “暗无天日” 的日子,定会迎来属于我们豁然开朗地一刻!让我们一起为心中所想,去奋斗吧!!


以下内容干货满满,跟上步伐吧~



🎒选择题【全面深度剖析】

📗 考点:for 循环的理解和应用

1、 设变量已正确定义,以下不能统计出一行中输入字符个数(不包含回车符)的程序段是( )


  • A:n=0; while(ch=getchar() != '\n') n++;

  • B:n=0; while(getchar() != '\n') n++;

  • C:for(n=0; getchar() != '\n'; n++);

  • D: n=0; for(ch=getchar(); ch != '\n'; n++);


:see_no_evil:大家觉得答案是什么呢


:hear_no_evil:答案是 D 啦~


:speak_no_evil: 如果有疑惑,且听我细细分析呀


本题的主要考点:"for 循环"


💡本题的解题关键:


  • 理解getchar库函数和for循环的使用原理


特别注意:


  • 1️⃣对于getchar库函数:每次只会从从键盘缓冲区读取一个字符,且遇到\n结束读取

  • ➡️即我们通过键盘输入的字符都会先进入键盘缓冲区,直到按下回车(\n)【此时\n才会输入到缓冲区】,字符才会从缓冲区中输入到电脑,被程序所读取 【\n还在缓冲区中,等待程序的下次读取】

  • 2️⃣对于for循环:

  • 第一个参数为循环的初始化【只执行一次】

  • 第二个参数为循环的判断条件【每次进行条件判断,决定是否进入下次循环】

  • 第三个参数为每次循环都执行的语句


👉有了以上了解,这题就很简单啦


💥对于 for 循环,其中第一项初始化表达式只执行一次,因此 ch 只从输入流中取一个字符,之后就再不会取字符,因此会死循环


✨这也就是为什么答案是D



📕考点:while 循环嵌套的理解的和应用

2、 运行以下程序后,如果从键盘上输入 65 14 <回车> ,则输出结果( )


<u><code class="language-c">int main(){    int m, n;        printf("Enter m,n;");        scanf("%d%d", &m,&n);        while (m!=n) //Ⅰ    {        while(m>n)         {            m=m-n; //Ⅱ        }        while(n>m)         {            n=n-m; //Ⅲ        }    }     printf("m=%d\n",m);     return 0;}</code></u>
复制代码


  • A:3 B: 2 C:1 D:0


👉同学们做这些题目的时候一定要耐心哦~


:see_no_evil:同学们觉得答案是什么呢


:hear_no_evil:答案是 C 啦~


:speak_no_evil: 如果同学们有疑惑,且听我细细分析呀


本题主要考点:**“while 循环嵌套的理解的和应用”**


💡接下来让我们一步一步解题吧:


➡️ 初值 m=64,n=16


  • 🫖循环Ⅰ 判断为真,进入循环 Ⅰ

  • 🍵循环Ⅱ 判断为真,进入循环Ⅱ

  • ☕循环Ⅱ 内执行m=m-n,至 m=19,n=14,循环Ⅱ 结束,跳出循环Ⅱ

  • 🍵 循环Ⅲ 判断为真,进入循环Ⅲ

  • ☕循环Ⅲ 内执行执行n=n-m,至 m=9,n=5,循环Ⅲ 结束 ,跳出循环Ⅲ

  • 🫖 重新进入循环Ⅰ ,如此反复循环至n==m跳出循环Ⅰ


✨此时m == n == 1,所以答案为C



📘考点:break 在 switch 语句中的理解和应用

3、 若运行以下程序时,从键盘输入 ADescriptor<回车> ,则下面程序的运行结果是( )


<u><code class="language-c">#include <stdio.h>int main(){    char c;        int v0=0,v1=0,v2=0;        do    {        switch(c=getchar())        {        case'a':        case'A':        case'e':        case'E':        case'i':        case'I':        case'o':        case'O':        case'u':        case'U':            v1 += 1;        default:            v0+= 1;            v2+=1;        }    }while(c!='\n');        printf("v0=%d,v1=%d,v2=%d\n",v0,v1,v2);        return 0;}</code></u>
复制代码


  • A: v0=7,v1=4,v2=7

  • B: v0=8,v1=4,V2=8

  • C: v0=11,v1=4,v2=11

  • D: v0=12,v1=4,v2=12

  • :see_no_evil:同学们觉得答案是什么呢


    :hear_no_evil:答案是 D 啦~

  • :speak_no_evil: 如果同学们有疑惑,且听我细细分析呀


本题主要考点:**“break 在 switch 语句中的理解和应用”**


💡解题关键:


  • 理解 break 在 switch 中的作用


➡️简单来说:


  • 每次进入 switch 语句中相当于找到入口,而case语句则为里面的每个房门,程序会根据你输入的信息进入到对应的房间

  • breakcase语句内相当于一个限制,只允许访问这个房间,访问完就直接结束switch语句,送到出口


特别注意:


  • 如果每个case语句内如果没有break语句,则程序就会肆无忌惮地访问每个房间直至遇到break语句或者访问完整个switch程序跳出


💫有了以上了解,这题就很简单啦~


  • 1️⃣例如当 c 为A时,从 case :A进入,直到执行v1+=1;,再执行v0+=1;v2+=1;

  • 2️⃣而当 c 为p时,从default进入,先执行v0+=1;,再执行v2+=1;,容易看出最终v0 == v2


📙考点:升序插入排序算法的理解和应用

4、 以下程序段的功能是( )


<u><code class="language-c">int a[] = {4, 0, 2, 3, 1}, i, j, t;
for(i = 1;i < 5;i++){ t = a[i]; j = i - 1; while(j >= 0 && t < a[j]) { a[j + 1] = a[j]; --j; } a[j + 1] = t; }</code></u>
复制代码


  • A: 对数组a进行插入排序(升序)

  • B: 对数组a进行插入排序(升序)

  • C: 对数组a进行选择排序(升序)

  • D: 对数组a进行选择排序(降序)

  • :see_no_evil:同学们觉得答案是什么呢


    :hear_no_evil:答案是 B 啦~

  • :speak_no_evil: 如果同学们有疑惑,且听我细细分析呀


本题主要考点:**“`升序插入排序算法的理解和应用”**


💡我们先来了解什么是升序插入排序算法


  • 插入排序算法是所有排序方法中最简单的一种算法,其主要的实现思想:

    • 是将数据按照一定的顺序一个一个的插入到有序的表中,最终得到的序列就是已经排序好的数据



直接插入排序插入排序算法中的一种


👉其算法采用的方法是:


  • 在添加新的记录时,使用顺序查找的方式找到其要插入的位置,然后将新记录插入


❗注意,下面超详细、易懂讲解:


➡️例如采用直接插入排序算法将无序表{3,1,7,5,2,4,9,6}进行升序排序的过程为:


  • 首先考虑记录 3 ,由于插入排序刚开始,有序表中没有任何记录,所以 3 可以直接添加到有序表中,则有序表和无序表可以如图所示:


  • 向有序表中插入记录 1 时,同有序表中记录3进行比较,1<3,所以插入到记录 3 的左侧,如图所示:


  • 向有序表插入记录 7 时,同有序表中记录 3 进行比较,3<7,所以插入到记录 3 的右侧,如图所示:


  • 向有序表中插入记录5 时,同有序表中记录 7 进行比较,5<7,同时 5>3,所以插入到 3 和 7 中间,如图所示:


  • 向有序表插入记录 2 时,同有序表中记录 7进行比较,2<7,再同 5,3,1 分别进行比较,最终确定 2 位于 1 和 3 中间,如图所示:


  • 照此规律,依次将无序表中的记录 496插入到有序表中,如图所示:



✨以上是不是对升序插入排序算法有跟深入的理解了呢?


➡️对于题目来讲,也是相同的道理:


  • 第 i 次排序时,t=a[i]作为临时变量保存这一次待插入值

  • j=i-1 故而 while 循环中 j 是从下标 i 的前一项开始向下标 0 遍历,判断 t<a[j]为真时 a[j+1]=a[j],j+1 在遍历之初是等于 i 的

  • 也就是将下标 i 位置用前边较大的值覆盖,依次把前边的元素后移,直到 a[j]不大于 t 的时候将 t 插入到下标 j+1 位置,使得前 i 个元素达到有序,方便第 i+1 次排序操作

  • 所以第 i 次排序时前边 i-1 个元素都是有序的


✨综上:就是对数组a进行插入排序(升序)



📓考点:循环嵌套的理解和应用

5、 执行下面的程序段,语句 3 的执行次数为( )


<u><code class="language-c">for(i = 0; i <= n-1; i++) // (1)    for(j = n; j > i; j--) // (2)        state; // (3)</code></u>
复制代码


  • A: n(n+2)/2 B: (n-1)(n+2)/2 C: n(n+1)/2 D: (n-1)(n+2)


:see_no_evil:同学们觉得答案是什么呢


:hear_no_evil:答案是 C 啦~


:speak_no_evil: 如果同学们有疑惑,且听我细细分析呀


本题主要考点:**“循环嵌套的理解和应用”**


💡解题关键:


  • 找规律


➡️方法:


  • 外循环有 n 次,当 i=0,内循环为 n 次,当 i=1,内循环为 n-1 次,当 i=2 时,内循环为 n-2 次

  • 以此类推:总次数为n+(n-1)+(n-2)+......+2+1,就是个等差数列


✨所以等差数列求和为:n(n+1)/2次,所以选C



📖编程题【全面深度解析】

🏷️【leetcode 题号:645. 错误的集合】【难度:简单】

1、 集合 s 包含从 1 n 的整数。不幸的是,因为数据错误,导致集合里面某一个数字复制了成了集合里面的另外一个数字的值,导致集合 丢失了一个数字 并且 有一个数字重复 。


给定一个数组 nums代表了集合 S 发生错误后的结果。


  • 输出描述:请你找出重复出现的整数,再找到丢失的整数,将它们以数组的形式返回。


:mag:题目传送门:OJ链接


示例:    输入:nums = [1,2,2,4] 、 nums[1,1]
输出: [2,3] [1,2]
复制代码


💡解题关键:


➡️将数组排序后,比较每对相邻的元素,即可找到错误的集合:


  • 1️⃣寻找重复的数字较为简单,如果相邻的两个元素相等,则该元素为重复的数字

  • 2️⃣寻找丢失的数字较为复杂,可能有以下两种情况:

  • 1.如果丢失的数字>1<n,则一定存在相邻的两个元素的差=2,这两个元素之间的值则为丢失的数字

  • 2.如果丢失的数字1n,则需要另外判断

  • 为了寻找丢失的数字,需要在遍历已排序的数组的同时记录上一个元素,如何计算当前元素与上一个元素的差值【因为丢失的数字有可能为1,因此需要将上一个元素初始化为 0】

  • 当前丢失的数字<n时,通过计算当前元素与上一个元素的差,即可得丢失得数字

  • 如果到末尾nums[n-1] != n ,则丢失的数字是n


👉实现:


void* cmp_int(void* a, void* b) {    return (int*)*a - (int*)*b;}
int* findErrorNums(int* nums, int numsSize, int* returnSize) { int* errorNums = malloc(sizeof(int) * 2); *returnSize = 2; qsort(nums, numsSize, sizeof(int), cmp_int); //先进行排序 int past = 0; //令上一个元素 = 0 for (int i = 0; i < numsSize; i++) { int now = nums[i]; //当前元素 if (curr == prev) {//找重复的元素 errorNums[0] = prev; } else if (curr - prev > 1) {//找小时的元素 errorNums[1] = prev + 1; } past = now; } if (nums[numsSize - 1] != numsSize) { errorNums[1] = numsSize; } return errorNums;}

复制代码



🏷️【牛客网题号: OR141 密码检查】【难度:简单】

2、 小明同学最近开发了一个网站,在用户注册账户的时候,需要设置账户的密码,为了加强账户的安全性,小明对密码强度有一定要求:


  • 1️⃣ 密码只能由大写字母,小写字母,数字构成;

  • 2️⃣ 密码不能以数字开头;

  • 3️⃣密码中至少出现大写字母,小写字母和数字这三种字符类型中的两种;

  • 4️⃣ 密码长度至少为 8


现在小明受到了 n 个密码,他想请你写程序判断这些密码中哪些是合适的,哪些是不合法的。


  • 输入描述: 输入一个数 n ,接下来有 n(n≤100) 行,每行一个字符串,表示一个密码,输入保证字符串中只出现大写字母,小写字母和数字,字符串长度不超过 100 。

  • 输出描述: 输入 n 行,如果密码合法,输出 YES ,不合法输出 NO


:mag:题目传送门:OJ链接


示例:    输入:1        CdKfIfsiBgohWsydFYlMVRrGUpMALbmygeXdNpTmWkfyiZIKPtiflcgppuR    输出:YES
复制代码


💡解题关键:


  • 只需要判断密码中的每个字符每种形式(大写字符,小写字符,数字,其它字符)统计出来,让后逐个判断判断是否符合题目条件即可。


👉实现:


#include<stdio.h>#include<string.h>int main(){    int n = 0;    while(~scanf("%d",&n))    {        for(int i = 0; i < n; i++)        {            char pwd[101] = {0};            scanf("%s",pwd);            int lower = 0,higher = 0,digit = 0,other = 0;            if(pwd[0] >= '0' && pwd[0] <= '9')            {                printf("NO\n");                continue;            }//密码不能以数字开头            if(strlen(pwd) < 8)            {                printf("NO\n");                continue;            }//密码长度至少为8            for(int i = 0; pwd[i] != '\0'; i++)            {                if(pwd[i] >= '0' && pwd[i] <= '9')                    digit++;//数字                else if(pwd[i] >= 'a' && pwd[i] <= 'z')                    lower++;//小写字母                else if(pwd[i] >= 'A' && pwd[i] <= 'Z')                    higher++;//大写字母                else                    other++;            }            if(other != 0)            {                printf("NO\n");                continue;            }// 密码只能由大写字母,小写字母,数字构成          //大写,小写,数字,必须具有两种以上,而比较运算真则1,假则0            if((lower > 0) + (higher > 0) + (digit > 0) < 2)            {                printf("NO\n");                continue;            }//密码只有1种字符            printf("YES\n");        }    }    return 0;}
复制代码



🌐 如何高效学习数据结构与算法?

数据结构与算法的学习还是得基础知识自己动手同步进行


如果是初学者,需要找一个可以在线练习得网站,我建议你去牛客网多练习呀(快点击跳转学起来吧!)



就如上述讲解的面试 OJ 题,牛客网内还有大神提供题解思路,对新手玩家及其友好,有不清楚的语法,不理解的地方,看看别人的思路,别人的代码,也许就能豁然开朗~



✨总结

综上,特辑的第四章呐:lollipop:~


让我们大家一同在平凡的生活中奔赴热爱吧~


毕竟,


“热爱的东西 永远不要说放弃”


:dizzy:如果有错误❌,欢迎指正呀:dizzy:


:sparkles:如果觉得收获满满,可以点点赞👍支持一下哟~:sparkles:



发布于: 刚刚阅读数: 4
用户头像

Dream-Y.ocean

关注

还未添加个人签名 2022.06.17 加入

还未添加个人简介

评论

发布
暂无评论
第四章 C语言之牛客网刷题📖笔记_c_Dream-Y.ocean_InfoQ写作社区