问题描述:

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

分析:

首先由用户输入人数n,然后对这n个人进行编号【因为如果不编号的话,我们就不能知道最后是哪位童鞋留下来了:)】

然后就开始了一圈一圈的循环,不断形成新的圈子,不断有人被淘汰,那么循环到什么时候截止呢?对只剩最后一个人,也就是说淘汰n-1了个人的时候,这个时候停止循环。

在实际情况中,应该是这n个人一开始围成了一个大圈子,然后随着不断的淘汰,圈子不断减小,最后剩下的那个人的一开始的编号就是我们要的结果。

我在用数组来表示这些人,因为进行了初始化,所以数组中元素的值都是原来的编号,因此我们只需要将被淘汰的人对应的数组元素的值设置为0即可。然后随着不断的循环,最后只剩下一个值不为0的数组元素,这个元素就是我们要的结果。

程序代码:

#include<iostream>
#define MAXNUM 100
using namespace std;
int main()
{
int a[MAXNUM];
int n=0; //n表示一共多少人
int m=0; //m表示被淘汰的人数
int i=1; //每轮循环中的计数器
int k=0; //用来表示报数的数
int j=0; //用于循环的计数器
cout<<"请输入总人数:";
cin>>n;
//对数据进行初始化操作,给每个人进行编号
for(j=1;j<=n;j++)
{
a[j]=j;
}
//通过循环不断淘汰人,直到最后只剩下一个人
while(m < n-1)
{
if(a[i]!=0) //判断该人是否已经淘汰
{
k++;
}
if(k == 3)
{
a[i]=0; //淘汰报数为3的人(即将其值设置为0)
k=0; //将k置为0,重新报数
m++; //对淘汰人数进行计数
}
i++; //对下一个人进行判断
if(i == n+1) //到了圈子的末尾出处,下一个位置将是圈子的开始
{
i=1; //将下一个人置为 1(圈子的开始位置 )
}
}
for(j=1;j<=n;j++)
{
if(a[j]!=0)
{
cout<<"\n最后剩下的人原来的编号为:"<<a[j]<<" 的人\n"<<endl;
}
}
return 0;
}

运行界面:

延伸思考:

将用于淘汰的数字设置为变量:

上面的题目中人数n是一个变量,但是数到3就淘汰,这个数组是确定的,我们想要这个用于淘汰的数组t也作为变量,要怎么修改呢?

其实不用太大的修改,只需要设置一个变量,并由用户输入数据完成初始化,然后用来作为淘汰的数字,程序代码如下:

#include<iostream>
#define MAXNUM 100
using namespace std;
int main()
{
int a[MAXNUM];
int n=0; //n表示一共多少人
int m=0; //m表示被淘汰的人数
int i=1; //每轮循环中的计数器
int k=0; //用来表示报数的数
int j=0; //用于循环的计数器
int t=0; //用于淘汰的数字变量
cout<<"请输入总人数n:";
cin>>n;
cout<<"请输入用于淘汰的数字t:";
cin>>t;
//对数据进行初始化操作,给每个人进行编号
for(j=1;j<=n;j++)
{
a[j]=j;
}
//通过循环不断淘汰人,直到最后只剩下一个人
while(m < n-1)
{
if(a[i]!=0) //判断该人是否已经淘汰
{
k++;
}
if(k == t)
{
a[i]=0; //淘汰报数为3的人(即将其值设置为0)
k=0; //将k置为0,重新报数
m++; //对淘汰人数进行计数
}
i++; //对下一个人进行判断
if(i == n+1) //到了圈子的末尾出,下一个位置将是圈子的开始
{
i=1; //将下一个人置为 1(圈子的开始位置 )
}
}
for(j=1;j<=n;j++)
{
if(a[j]!=0)
{
cout<<"\n最后剩下的人原来的编号为:"<<a[j]<<" 的人\n"<<endl;
}
}
return 0;
}

程序运行界面:

使用单链表解决该问题

这个问题中的n虽然看起来是变量,但是我们通过代码可以看出来,它其实是有一个上线MAXNUM的,也就是当用户输入的n大于MAXNUM的时候就会出错。

那么,我们应如何写出真正意义上的可以让用户输入一个不受到限制的变量呢(实际上无论如何都收到数据类类型长度的限制的=.=)?

并且,当n很大的时候,我们就需要在内存中开辟一块连续的内存空间,在内存比较小的时候,这样做有可能无法分配内存,而单链表即满足了逻辑上的连续,而物理上却可以是不连续的。

(关于C++中的单链表,如果不是很明白可以看看这篇文章:C++中单链表的建立和操作

示例代码如下:

#include<iostream>
using namespace std;
struct Node
{
int num;
Node *next;
};
Node * Add(Node *head,int i)
{
Node *node,*htemp;
if(!(node = new Node))
{
cout<<"分配内存失败!"<<endl; //分配内存失败
return NULL;
}
else
{
node->num=i; //保存结点数据
node->next = NULL; //设置结点指针为空,即作为表尾
if(head == NULL) //当链表是空表的时候
{
head = node;
return head;
}
htemp = head;
while(htemp->next != NULL) //查找链表的末尾
{
htemp = htemp->next;
}
htemp->next = node;
return head;
} }
Node *FindNodeNum(Node *head,int k)
{
Node *htemp;
int i = 1;
htemp = head; //保存链表头指针
for(i = 1;i<k&&htemp;i++) //找到该结点
{
htemp = htemp->next;
}
return htemp; //返回指向第k个结点的指针
}
int main()
{
int n=0; //n表示一共多少人
int m=0; //m表示被淘汰的人数
int i=1; //每轮循环中的计数器
int k=0; //用来表示报数的数
int j=0; //用于循环的计数器
int t=0; //用于淘汰的数字变量
cout<<"请输入总人数n:";
cin>>n;
cout<<"请输入用于淘汰的数字t:";
cin>>t;
//对数据进行初始化操作,给每个人进行编号
Node *head=NULL;
for(j=1;j<=n;j++)
{
head=Add(head,j);
}
Node *nodeData;
//通过循环不断淘汰人,直到最后只剩下一个人
while(m < n-1)
{
nodeData=FindNodeNum(head,i);
if(nodeData->num!=0) //判断该人是否已经淘汰
{
k++;
}
if(k == t)
{
nodeData->num=0; //淘汰报数为3的人(即将其值设置为0)
k=0; //将k置为0,重新报数
m++; //对淘汰人数进行计数
}
i++; //对下一个人进行判断
if(i == n+1) //到了圈子的末尾出,下一个位置将是圈子的开始
{
i=1; //将下一个人置为 1(圈子的开始位置 )
}
}
for(j=1;j<=n;j++)
{
nodeData=FindNodeNum(head,j);
if(nodeData->num!=0)
{
cout<<"\n最后剩下的人原来的编号为:"<<nodeData->num<<" 的人\n"<<endl;
}
}
return 0;
}

运行界面:

C++经典题目:有n个人围成一圈,顺序排号,然后数数进行淘汰的解法和一些思考的更多相关文章

  1. 【转】约瑟夫环算法---------题目:有n个人围成一圈,顺序排号,从第一个开始报数(从1到3报数),凡报到3的人退出圈子,问最后最后留下的是原来第几号的那位.

    提示:用环形链表实现 对于这个题目其实就是用c语言的循环链表实现一个约瑟夫环.我们可以定义一个循环链表,将这n个人加入到链表中,然后定义三个节点指针在链表上循环,移动跨度为3,利用链表的循环功能每次删 ...

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

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

  3. 某厂java算法题实现及改进【有n个人成一圈,顺序排号(编号为1到n),从第一个人开始报数1到3报数】

    一.第一种实现: 实现比较简单,直接贴现成的代码了,第一种实现: /** * 总人数 * * @param d */ private static void sortQuerry1(int d) { ...

  4. 经典算法:n个人围成一圈,报m的离开,最后剩下谁?

    public int remainPersonNumber(int n, int m) { //输入不合法 if(n < 1 || m < 1) return -1; //初始化,存入Li ...

  5. n人围成一圈报数

    题目:有n个人围成一圈,顺序排号.从第一个人开始报数(从1到3报数),凡报到3的人退出圈子,问最后留下的是原来的第几号的那位 思路:用一个数组存这n个人,里面的初始状态全设为1,表示都还在圈子里面. ...

  6. java解答:有17个人围成一圈(编号0~16),从第0号的人开始从1报数,凡报到3的倍数的人离开圈子,然后再数下去,直到最后只剩下一个人为止,问此人原来的位置是多少号?

    package ttt; import java.util.HashMap; import java.util.Map.Entry; /** * 有17个人围成一圈(编号0~16),从第0号的人开始从 ...

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

    首先,我最大的学习来源不是百度而是我群友~~在这里表白一波我热爱学习的群友们!然后今天群里突然有人提出了题目的这个问题:有n个人围成一圈,顺序排号.从第一个人开始报数(从1到3报数),凡报到3的人退出 ...

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

    1 /*37 [程序 37 报数] 2 题目:有 n 个人围成一圈,顺序排号.从第一个人开始报数(从 1 到 3 报数),凡报到 3 的人退出圈子, 3 问最后留下的是原来第几号的那位. 4 */ 5 ...

  9. C语言——N个人围成一圈报数淘汰问题

    <一>问题描述: 有17个人围成一圈(编号为0-16),从第 0号的人开始从 1报数, 凡报到 3的倍数的人离开圈子,然后再数下去,直到最后只剩下一个人为止. 问此人原来的位置是多少号? ...

随机推荐

  1. zendstudio正则匹配查询

    Ctrl+H之后,显示的File Search标签页为Containing text. Alt+/ 帮助提示正则匹配的语法. 例子如下: select type from table where id ...

  2. new关键字在虚方法的动态调用中的阻断作用

    关于new关键字在虚方法动态调用中的阻断作用,也有了更明确的理论基础.在子类方法中,如果标记 new 关键字,则意味着隐藏基类实现,其实就是创建了与父类同名的另一个方法,在编译中这两个方法处于动态方法 ...

  3. json数据相对于xml数据.

    JSON is a valid subset of JavaScript, Python, and YAML JSON parsing is generally faster than XML par ...

  4. 使用WebFrom来模拟一些MVC的MODEL与View的数据交互功能

    MVC中有一点非常闪瞎人眼的功能就是,可以根据Model与View视图来直接将页面也数据模型进行绑定,那么我们在想客户端发送页面时不需要进行各种控件赋值,不需要操心怎么渲染,当客户提交表单给服务器时也 ...

  5. C/C++安全编码-字符串

    1 字符串     1.1 字符串基础 字符串提供命令行参数.环境变量.控制台输入.文本文件及网络连 接,提供外部输入方法来影响程序的行为和输出,这也是程序容易出错的地方.字符串是一个概念,并不是C/ ...

  6. rails 中 create, new, build, save 的用法以及误区汇总

    自己很初级,初级的不能再初级,所以初次接触rails的时候,对于里面的create,new,build等方法不是很了解,用的很混乱,导致经常出现不必要的bug,很苦恼,决定,总结一下,结合网上已有资源 ...

  7. 多线程09-Lock和Condition

    1.概念 Lock比传统线程模型中的synchronized方式更加面向对象,与生活中的锁类似,锁本身也应该是一个对象.两个线程执行的代码片段要实现同步互斥的效果,它们必须用同一个Lock对象. 2. ...

  8. 搭建Memcached + php 缓存系统

    服务器环境,Centos6.5 1.安装Memcached服务端 Yum -y install memcached 2.配置Memcached服务端用户以及自动启动服务等 将服务配置成自启动 chkc ...

  9. xml配置与使用

    php100:89:xml常识知识补充 xml常识知识补充XML(即可扩展标记语言,它与HTML一样,都是标准通用标记语言.Xml是Internet环境中跨平台的,依赖于内容的技术.扩展标记语言XML ...

  10. 函数式编程做用户登陆注册练习-pycharm上

    def login(username,password): """ 用户登陆 :param username: 用户名 :param password:密码 :retur ...