题解:报数问题(C++描述)

题目相关

题目描述

有n人围成一圈,顺序排号。从第1个人开始报数(从1到3报数),凡报到3的人退出圈子,问最后留下的是原来的第几号的那位。

输入

初始人数n

输出

最后一人的初始编号

分析

​ 在读完题目发现,这道题目就是需要我们模拟循环报数的过程,可以想象一下小时候玩击鼓传花时候的情景。这道题目的难点在于如何判断某个同学是不是还在队伍中,不是简单的判断是否是3的倍数,这种方法,仅适用于不循环的报数,一旦首尾相连,倍数的判断就不太合适了。

构造数组表明学生的状态

​ 每个同学在这道题目中的数据信息有两个,学号(编号),是否在队伍中(在/不在)。如何采用一定的方法,将这两者结合起来则能迅速处理这一问题。此时,我们可以构造一个标记数组,将这两者结合起来。将数组的下标作为学生学号,存储的内容用来表示学生状态。共有两个状态,我们可以使用布尔类型(bool)数组分别用true和false来表示两种状态,也可以使用整数类型数组表示对应状态,为了方便从下标1开始,开辟空间时可开辟人数+1的空间。

//开辟bool类型数组stu,用来表示各个学生的状态
//stu[x] 为true 表示报到了3不在队伍中, false 表示还在队伍中
bool *stu = new bool[n + 1];// n 为学生人数

利用取余实现模拟循环

​ 该题的另一个难点在于怎么进行循环?无论是 从1~3反复进行报数还是,n个同学围成一圈,都涉及到了这一点。一种方法是判断,当判断到结尾时,将值重新改成开头。类似下面这样

if(num==3) num=1;
if(i==n) i=1;

但这么写有些麻烦,也得需要考虑变化过程对他的影响。这事我们可以考虑另一种方法,使用取余符号(%)进行模拟。

已知%符号的作用是获取余数,例如 7%5=2。当能整除时,结果为0。所以当一个数字%n时,结果一定在0~n-1之间。并且当a%b,a<b时,a%b=a。利用这些特性可以写出这样的一个式子:x=(x+1)%n ,这样x能变成x+1;当x为n-1时,x会变成0,不断重复x就能在0n-1之间循环。若想在1n之间循环可以修改成x=x%n+1。

int i = 1;      //学生的学号 1~n
while (ren > 1) //循环报数,直到剩下一个人
{
    if (stu[i] == false) // 如果在队伍中
    {
        num = num % 3 + 1; //报数
        if (num == 3)
        {                  //报到3
            stu[i] = true; //退出队伍
            ren--;         //在队伍中的人数减一
        }
    }

    i = i % n + 1; //下一个学生的编号
}

枚举法找出最后剩下的人的编号

最后只剩下最后一人,必定是这样的状态:所有人都是true,只有他是false。那么我们只需要枚举遍历下,找出状态为false的即可。

for (int j = 1; j <= n; j++)
{//枚举学号1~n的同学
    if (stu[j] == false)
    {//当状态为false,则说明j在队伍中
        cout << j;//输出编号
        break;//结束循环
    }
}

代码实现

#include <iostream>
#include <cstring>
using namespace std;
int main()
{
    //n-存储人数 num-报的数字 ren-留下的人数
    int n, num = 0, ren; 
    
    cin >> n;            // 输入在人数
    ren = n;             //确定在队伍中的人数

    //开辟bool类型数组stu,用来表示各个学生的状态
    //stu[x] 为true 表示报到了3不在队伍中, false 表示还在队伍中
    bool *stu = new bool[n + 1];

    //初始化 stu,使初始值为false
    memset(stu, false, sizeof(bool) * (n + 1));

    int i = 1;      //学生的学号 1~n
    while (ren > 1) //循环报数,直到剩下一个人
    {
        if (stu[i] == false) // 如果在队伍中
        {
            num = num % 3 + 1; //报数
            if (num == 3)
            {                  //报到3
                stu[i] = true; //退出队伍
                ren--;         //在队伍中的人数减一
            }
        }

        i = i % n + 1; //下一个学生的编号
    }

    for (int j = 1; j <= n; j++)
    {//枚举学号1~n的同学
        if (stu[j] == false)
        {//当状态为false,则说明j在队伍中
            cout << j;//输出编号
            break;//结束循环
        }
    }

    return 0;
}

做题时,可从全局角度出发,将题目分解成若干个小问题,解决后再整合起来。通过本题,可以练习数组的构造使用以及循环的处理。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,921评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,635评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,393评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,836评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,833评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,685评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,043评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,694评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,671评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,670评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,779评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,424评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,027评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,984评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,214评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,108评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,517评论 2 343

推荐阅读更多精彩内容

  • Java经典问题算法大全 /*【程序1】 题目:古典问题:有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子...
    赵宇_阿特奇阅读 1,841评论 0 2
  • 官网 中文版本 好的网站 Content-type: text/htmlBASH Section: User ...
    不排版阅读 4,365评论 0 5
  • 第四天 数组【悟空教程】 第04天 Java基础 第1章数组 1.1数组概念 软件的基本功能是处理数据,而在处理数...
    Java帮帮阅读 1,584评论 0 9
  • 在C语言中,五种基本数据类型存储空间长度的排列顺序是: A)char B)char=int<=float C)ch...
    夏天再来阅读 3,323评论 0 2
  • 1.把二元查找树转变成排序的双向链表 题目: 输入一棵二元查找树,将该二元查找树转换成一个排序的双向链表。 要求不...
    曲终人散Li阅读 3,293评论 0 19