【C语言每日题解】三题:回文检查、刘备 关羽 张飞三人过年放鞭炮、约瑟夫环问题(犹太人死亡游戏)(难度up,推荐)

news2024/12/23 18:19:37

 18d55529065a4bc5999e1517e976f942.gif2f10399c4fa5412c9b50f75ceef13b40.gif🥰欢迎关注 轻松拿捏C语言系列,来和 小哇 一起进步!✊

🌈感谢大家的阅读、点赞、收藏和关注

🥰希望大家喜欢我本次的讲解

🌟非常推荐最后一道题 🌹 犹太人死亡游戏,建议观看


🌙目录

💕题目一:回文检查

🎉题目二:刘备、关羽、张飞过年放鞭炮

🌹题目三: 犹太人死亡游戏

        所以我们要做的就是如何让数组中最后一个元素过了之后又来到开头的元素。

其次,该题还有一个要点:如何将总人数n储存进数组?因为n是变化的,由用户输入

        1.变长数组

        2.动态内存分配


 

 

💕题目一:回文检查

8bd10553eb624d69b4561eefc5008139.png

根据题目要求,我们可以知道要输入一个完整的英文句子,其中包括空格

        这里我们就要注意了,在scanf 中使用%s来输入字符串时,它会从第一个非空白字符开始读取,直到遇到空白字符就停止读取。也就是说我们这里不能使用scanf来直接读取含有空白的字符串

      gets()和 fgets()函数可以读取含有空白的字符串

 用法://gets()

            char arr[100];  
            gets(arr); // 读取直到换行符或EOF,但不检查缓冲区大小

 

            //fgets()

            char arr[100];

            fgets(arr, sizeof(arr), stdin); // 读取最多 sizeof(arr)-1 个字符,或直到换行符或EOF

                //stdin为标准输入

        另外,gets没有fgets安全,因为前者不检查缓冲区大小,可能导致缓冲区溢出

我们知道了如何输入一个包含空格的英文句子后,按题目要求 不考虑空格和标点符号,所以接着我们就要想办法除去空格和标点。

        这里我想到的是可以利用ASCII码表,根据不同字符的ASCII码值的不同,我们将每一个字符进行条件判断 如果它在英文大写字母A~Z之间或英文小写字母 a~z之间,那么就留下;

        否则就不是字母即为空格或其他符号,那么就不要。

// 函数:检查字符是否为字母  
int is_alpha(char c) {
    return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
}
// 函数:移除字符串中的空格和标点符号,并返回处理后的字符串长度  
int remove(char* src, char* dest) {
    int i, j = 0;
    for (i = 0; src[i] != '\0'; i++) {
        if (is_alpha(src[i])) {
            dest[j++] = src[i]; 
        }
    }
    dest[j] = '\0'; // 添加字符串终止符  
    return j;
}

我们拿到只有字母的字符串后,就可以把它逆置,然后再和逆置之前的去比较,如果每个字符都相同,则是;有不同,则不是。

当然这里也可以不用逆置,让字符串首尾元素比较也可以判断。

// 函数:检查两个字符串(已处理,忽略空格和标点符号)是否为回文
// //方法二,字符数组首尾元素对比检查  
int check2(char* str1, char* str2, int len) 
{
    int i;
    for (i = 0; i < len / 2; i++) {
        if (str1[i] != str2[len - i - 1]) {
            return 0; // 不是回文  
        }
    }
    return 1; // 是回文  
}
// 方法一  将逆置和原来的字符数组对比
int check1(char* str1, char* str2, int len)
{
    int i;
    for (i = 0; i < len; i++)
    {
        if (str1[i] != str2[i])
            return 0;
    }
    return 1;
}

现在我们已经解决了这一道题了,来看一下完整代码

      代码实现       

// 函数:检查字符是否为字母  
int is_alpha(char c) {
    return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
}
// 函数:移除字符串中的空格和标点符号,并返回处理后的字符串长度  
int remove(char* src, char* dest) {
    int i, j = 0;
    for (i = 0; src[i] != '\0'; i++) {
        if (is_alpha(src[i])) {
            dest[j++] = src[i]; 
        }
    }
    dest[j] = '\0'; // 添加字符串终止符  
    return j;
}
// 函数:检查两个字符串(已处理,忽略空格和标点符号)是否为回文
// //方法二,字符数组首尾元素对比检查  
int check2(char* str1, char* str2, int len) 
{
    int i;
    for (i = 0; i < len / 2; i++) {
        if (str1[i] != str2[len - i - 1]) {
            return 0; // 不是回文  
        }
    }
    return 1; // 是回文  
}
// 方法一  将逆置和原来的字符数组对比
int check1(char* str1, char* str2, int len)
{
    int i;
    for (i = 0; i < len; i++)
    {
        if (str1[i] != str2[i])
            return 0;
    }
    return 1;
}
int main()
{
    char a[20];
    char b[20];
    fgets(a, sizeof(a), stdin);
    int len = remove(a, b); 
    // 检查处理后的句子和反转后的句子是否相同(忽略大小写)
    // 方法一 , 将逆置和原来的字符数组对比
     // 反转处理后的句子并检查是否为回文  
    char temp[20];
    int l = len - 1;
    for (int i = 0; i < len; i++)
    {
        temp[i] = b[l--];
    }
    if (check1(temp, b, len)) {
        printf("YES\n");
    }
    else {
        printf("NO\n");
    }

     //检查处理后的句子和反转后的句子是否相同(忽略大小写)  
     //方法二,字符数组首尾元素对比检查
    if (check2(b, b, len)) {
        printf("YES\n");
    }
    else {
        printf("NO\n");
    }
	return 0;
}

 

🎉题目二:刘备、关羽、张飞过年放鞭炮

520b3a58220c44e2ababfdcb7d56dd2b.png

根据规律可以发现有n个鞭炮时,刘备放炮的时间点在n,关羽的在2n-1,张飞的在3n-2。

         同样的鞭炮数量,张飞最后放完,所以他决定一共花了多少时间

现在来解决一共能听到多少声的问题。

        我们可以把他们每个人从放第1个鞭炮到放第n个鞭炮的时间点分别装进三个数组,比如 刘备的就是 {1,2,3,……n}

        接着数出一共有多少个时间点,当然相同的时间点只计算一次,比如n=1时,他们放炮时间点都为1,三个1一起响,所以只计一次;n=2时,时间点分别在2、3、4,不在同一个时间点,所以响三次,都要计数。

        数出有多少个时间点(相同点计一次),我们就知道一共有多少次响声。

      代码实现         

#include<stdio.h>

void Func1(int liu[], int num)//存储刘备放炮时间点
{
    int i = 0;
    for (i; i <num; i++)
    {
        liu[i] = i+1;
    }
}
void Func2(int guan[], int num)//存储关羽放炮时间点
{
    int i = 0;
    for (i; i < num; i++)
    {
        guan[i] = 2*i+1;
    }
}
void Func3(int zhang[], int num)//存储张飞放炮时间点
{
    int i = 0;
    for (i; i < num; i++)
    {
        zhang[i] = 3*i + 1;
    }
}
int sound(int liu[], int guan[], int zhang[], int n)
{
    int i;
    int temp = n;
    //将刘关二人放炮时间点放在一起,重复的只计一次
    for (i = 0; i < n; i++)
    {
        int j = 0;
        while(j<temp)
        {
            if (guan[i] == liu[j])
                break;
            else
                j++;
        }
        if (guan[i] != liu[j])
        {
            liu[temp] = guan[i];
            temp++;
        }
    }
    //将三人放炮时间点放在一起,重复的只计一次
    for (i = 0; i < n; i++)
    {
        int j = 0;
        while (j < temp)
        {
            if (zhang[i] == liu[j])
                break;
            else
                j++;
        }
        if (zhang[i] != liu[j])
        {
            liu[temp] = zhang[i];
            temp++;
        }
    }
    //三人响声次数
    return temp;
}
//刘备、关羽、张飞过年放炮问题
int main()
{
    int n = 0;
    scanf("%d", &n);//输入鞭炮数量
    int liu[100] = { 0 };
    int guan[100] = { 0 };
    int zhang[100] = { 0 };
    Func1(liu,n);
    Func2(guan,n);
    Func3(zhang,n);
    int count = sound(liu,guan,zhang,n);//响声
    printf("time = %d\n", 3 * n - 2);//时间
    printf("count = %d", count);
    return 0;
}

🌹题目三: 犹太人死亡游戏

45fd5a3e2c59414aa6560f267e62ae1f.png

5e3187eec28446fbb87864152136fe00.png​ 

这道题的思路和题目描述一样,定义一个长度为n的数组,数组元素一开始都为0,从第一个开始报数,报到m的人死亡,其对应元素赋值为1。

         我们需要注意的是如何让这个数组中活着的人能够循环报数,即让这些人像图中一样能够“围起来”   最后一个人报完数让下一个人接着报数。  

        所以我们要做的就是如何让数组中最后一个元素过了之后又来到开头的元素。

        在这里我学到一个非常巧妙的写法 

//举例(并非该题完整代码)

int arr [5] ={1,2,3,4,5};//假设n = 5

int m = 3;//假设 m = 3

int i = 0;

int count = 0;//计数

while(条件)

{        count++; 

        if(count = = m)    

        {

                arr[i] = 0;

                count = 0;

        }

          i = (i + 1) % 5; // 移动到下一个位置      

}

        我们给当前数组下标 i 赋值i +1 虽然也能到下一个元素arr[i+1],但是一直+1会超过数组arr的限度,导致缓冲区溢出 。但是我们采用 i = (i + 1) % 5 的写法 让i+1后 模上数组最大长度5,这样最后一个元素过了之后又能够来到开头的元素。

其次,该题还有一个要点:如何将总人数n储存进数组?因为n是变化的,由用户输入

        这里 简单 讲两个方法:1.变长数组

                                              2.动态内存分配

        1.变长数组

int n;

scanf("%d",&n);

int arr[n];

        但是在Visual Studio中 ,变长数组是不能使用的(😑我在牛客网答题遇到过)

        所以这里我们使用第二种方法

        2.动态内存分配

        使用要包含头文件 <stdlib.h>

        从堆区分配内存,使用完后再收回存储空间

        主要函数malloc、calloc、free

        这里我们只使用malloc和free

int n;

scanf("%d",&n);

int* arr = (int*)malloc(n*sizeof(int));//现在arr可以存储n个int类型的数字

if (ptr == NULL) {  
    ……
} // 处理内存分配失败的情况

……//使用arr

 //使用完释放内存块

 free(arr);

🆗回归题目,先来再简述一遍题干:

        有n个人一开始都为0,从第一个人开始报数(从1开始喊),谁报到数字m就死亡,然后他的0变成1 。下一个人又接着从1开始报数,谁报到数字m就死亡,他的0也变成1。一直持续,直到只剩两个活人,其他人都死了,即n个人里只有两个0,其余都是1,游戏结束🤣

        所以我们这个循环报数的条件可以是   活人数量>2,当最后只有两个活人时就结束循环。

        在循环里,即游戏进行中 ,大家都在报数时, 只有活人才报数,死人不报数(诈尸也不行哈哈)。每次报数从1~m,喊到m的人死,活人数量就减减。下一个活人报数就又从1开始喊。

        游戏结束后我们就可以开始找两个幸存者的编号,题上说他们的编号就是 下标+1,只需要遍历游戏结束后的数组去找0在哪里,我们就可以知道幸存者编号

      代码实现       

#include<stdio.h>
#include<stdlib.h>
void game(int *arr,int mm,int nn )
{
    int count = 0;//计数
    int i = 0;//下标
    int survivors = nn;//活人(幸存者)
    while ( survivors > 2)//不满足条件时,游戏结束
    {
        if (arr[i] == 0) // 如果当前人还是活人(死了变成1)
        { 
            count++; //活人就要报数,给我开始喊  
            if (count == mm) // 报数到mm时,0变1,活人死去
            {   
                arr[i] = 1; // 0-->1,人死
                count = 0;//后面的人重新报数  
                survivors--;//活人少一个
            }
        }
        i = (i + 1) % nn; // 下标移动到下一个位置,该下一个哥们 
    }
    //出了循环 游戏结束  找两个0的位置
    int j;
    int temp[2];//装两个0的编号
    int k = 0;
    for (j = 0; j < nn; j++)
    {
        if (arr[j] == 0)//找到0
        {
            temp[k] = j+1;//下标+1 就是题目要求的 编号
            k++;
        }
        if (k == 2)//两个0找到后,跳出循环
            break;
    }
    printf("Josephus 和他的朋友的位置:%d %d", temp[0], temp[1]);
}
//犹太人死亡游戏
int main()
{
    int n, m;
    printf("输入总人数n(2<n<1000):");
    scanf("%d", &n);
    printf("输入报数值(2<m<=n):");
    scanf("%d", &m);
    //动态分配内存
    int* arr = (int*)malloc(n * sizeof(int));
    if (arr == NULL) { // 检查malloc是否成功  
        printf("动态内存分配失败\n");
    }
    int h;
    for (h = 0; h < n; h++)
        arr[h] = 0;//活人一开始都是0
    game(arr,m,n);//调用函数,进入游戏
    //释放内存块
    free(arr);
    return 0;
}

​🎉🎉本次的内容结束啦,希望大家喜欢 能够看懂

😘💕希望大家能够三连支持,你们的鼓励是我前进的动力

🌹🌹谢谢观看!76162e179b1442aa805039e815b64dd4.gif

 

 

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

html--地图

<!DOCTYPE html> <html lang"en"> <head><meta charset"utf-8"><title>ECharts</title><!--Step:1 引入一个模块加载器&#xff0c;如esl.js或者require.js--><script src"js/esl.js"></scr…

RGMII基于V2.0规范解读

一、说明 RGMII&#xff08;Reduced Gigabit Media Independent Interface&#xff09;是Reduced GMII&#xff08;吉比特介质独立接口&#xff09;&#xff0c;旨在替代IEEE802.3u MII、IEEE802.3z GMII和TBI。主要目标是将MAC和PHY互连所需的引脚数量从最大28个引脚&#xf…

数据库原理与应用实验八 存储过程

目录 实验目的和要求 实验环境 实验内容与过程 实验内容&#xff1a; 操作过程&#xff1a; 实验目的和要求 熟悉存储过程的定义和使用&#xff0c;熟练运用 select ,update ,insert ,delete 命令完成对学生信息数据库的查询、更新、添加、删除操作。 实验环境 Windo…

k8s的整体架构及其内部工作原理,以及创建一个pod的原理

一、k8s整体架构 二、k8s的作用&#xff0c;为什么要用k8s&#xff0c;以及服务器的发展历程 1、服务器&#xff1a;缺点容易浪费资源&#xff0c;且每个服务器都要装系统&#xff0c;且扩展迁移成本高 2、虚拟机很好地解决了服务器浪费资源的缺点&#xff0c;且部署快&#x…

【从零开始学习Redis | 第十一篇】快速介绍Redis持久化策略

前言&#xff1a; Redis 作为一种快速、高效的内存数据库&#xff0c;被广泛应用于缓存、消息队列、会话存储等场景。然而&#xff0c;由于其特性是基于内存的&#xff0c;一旦服务器进程退出&#xff0c;内存中的数据就会丢失。为了解决这一问题&#xff0c;Redis 提供了持久…

删除表空间

Oracle从入门到总裁:​​​​​​https://blog.csdn.net/weixin_67859959/article/details/135209645 当某个表空间中的数据不再需要时&#xff0c;或者新创建的表空间不符合要求时&#xff0c;可以考虑删除这个表空间。若要删除表空间&#xff0c;则需要用户具有 DROP TABLESP…

【C++】认识C++(上)

目录 从C到C命名空间同名冲突命名空间的定义命名空间的使用 C的输入和输出缺省参数&#xff08;默认参数&#xff09; 从C到C C语言的出现是计算机科学和工程史上的一个重要里程碑&#xff0c;许多现代计算机语言都受C语言的影响。C语言是面向过程的&#xff0c;结构化和模块化…

社交媒体数据恢复:皮皮搞笑

一、数据恢复前的准备 在开始数据恢复之前&#xff0c;请确保您已经完成了以下准备工作&#xff1a; 确认您具有管理员权限&#xff0c;以便在操作过程中避免不必要的错误。 确保您的设备电量充足&#xff0c;以免在数据恢复过程中因电量不足而导致数据丢失。 如果您需要恢复…

解决el-upload组件上传文件403 Forbidden的问题

话不多说&#xff0c;上错误。网络显示&#xff1a; 控制台显示&#xff1a; 并且后端也没接收到任何的请求。 只需要把前端中的组件&#xff1a; action的路径修改为&#xff1a; 也就是不写前面的localhost&#xff0c;而是拼接上发送请求拼接的‘api’即可 可以看到&#x…

【前端】CSS基础(2)

文章目录 前言1、CSS选择器1.1选择器的功能1.2 选择器的种类1.2.1 基础选择器1.2.1.1 标签选择器1.2.1.2 类选择器1.2.1.3 id选择器1.2.1.4 通配符选择器1.2.1.5 伪类选择器 1.2.2 复合选择器1.2.2.1 后代选择器1.2.2.2 子选择器1.2.2.3 并集选择器 前言 这篇博客仅仅是对CSS的…

风电功率预测 | 基于RBF径向基神经网络的风电功率预测(附matlab完整源码)

风电功率预测 风电功率预测完整代码风电功率预测 基于RBF(径向基函数)神经网络的风电功率预测是一种常见的方法。RBF神经网络是一种前馈神经网络,其隐藏层使用径向基函数作为激活函数。 下面是一个基于RBF神经网络的风电功率预测的一般步骤: 数据收集:收集包括风速、风向…

鉴源论坛·观通丨轨交软件测试技术详述

作者 | 刘艳青 上海控安安全测评部测试经理 版块 | 鉴源论坛 观通 社群 | 添加微信号“TICPShanghai”加入“上海控安51fusa安全社区” 01 集成测试技术要求 1.1 总体要求 对软件集成测试进行静态测试应先于动态测试&#xff1b; 集成过程是动态进行的&#xff0c;在测…

软件工程期末复习(7)需求过程

需求分析 需求过程 什么是需求过程&#xff1f; 需求过程是用来导出、确认和维护系统需求文档的一组结构化活动。通常&#xff0c;一个良好的需求过程应包括下列活动&#xff1a; 需求提取需求分析和协商需求确认 需求提取 需求提取是通过与客户、系统用户和其他与系统开发相…

谷歌I/O 2024大会全面硬刚OpenAI

&#x1f989; AI新闻 &#x1f680; 谷歌发布升级版Gemini机器人 竞争OpenAI ChatGPT-4 摘要&#xff1a;谷歌展示了升级版的 Gemini 聊天机器人&#xff0c;其支持实时处理视频和语音输入&#xff0c;并准确回答问题。此次发布时机与 OpenAI 公布 ChatGPT-4o 新模型几乎同步…

C++多态实现原理详解

阅读引言&#xff1a; 我想象了一下&#xff0c; 假如人有突然问我什么是多态&#xff0c; 我该如何给别人说清楚呢&#xff1f;所以写下这篇文章&#xff0c; 希望大家看完有所收获。 目录 ①. 开胃小菜 ②. 多态常见的一个小小面试题 ③&#xff0c; 虚函数指针虚函数表 …

FPGA - Xilinx系列高速收发器---GTX

1&#xff0c;GTX是什么&#xff1f; GT &#xff1a;Gigabit Transceiver千兆比特收发器&#xff1b; GTX &#xff1a;Xilinx 7系列FPGA的高速串行收发器&#xff0c;硬核 xilinx的7系列FPGA根据不同的器件类型&#xff0c;集成了GTP、GTX、GTH、GTZ四种串行高速收发器&am…

ARM机密计算组件

安全之安全(security)博客目录导读 目录 ​一、硬件架构 1、RME 二、软件和固件架构 1、RMM 2、其他固件标准&#xff08;例如PSCI&#xff09; 三、开源实现 1、TF-A 2、Veraison 3、工具链 四、动态TrustZone技术 Arm机密计算架构(Arm CCA)引入了一系列硬件和软件…

信息化总体架构方法_2.信息化工程建设方法

1.信息化架构模式 信息化架构一般有两种模式&#xff0c;一种是数据导向架构&#xff0c;一种是流程导向架构。对于数据导向架构重点是在数据中心&#xff0c;BI商业智能等建设中使用较多&#xff0c;关注数据模型和数据质量&#xff1b;对于流程导向架构&#xff0c;SOA本身就…

如何利用3D可视化大屏提升信息展示效果?

老子云3D可视化平台https://www.laozicloud.com/ 引言 在信息爆炸的时代&#xff0c;如何有效地传达和展示信息成为了各行各业的一大挑战。传统的平面展示方式已经无法满足人们对信息展示的需求&#xff0c;3D可视化大屏应运而生&#xff0c;成为了提升信息展示效果的利器。本…