最后一个人站着,使用了圆形链表
Last man standing , used circular linked list
问题:一家公司招聘候选人,会让他们坐成一圈。他们每隔一秒就选择一个候选人,然后他离开圆圈(因此圆圈越来越小(,直到只剩下1个。所以,如果有5个人,它会像:-
1 2 3 4 5
1 3 4 5 (2 is selected)
1 3 5 (4 is selected)
3 5 (1 is selected)
3 (3 is left, does'nt get the job!)
Jhon是一个过度精明的人,他不想成为这个恶意公司的一员。
如果他知道总共有560人,他会站在哪里。回答:我试着制作一个程序,输入n(候选人数量(它将打印一个将被取消选择的座位的值。
我使用了循环链表和删除。
请耐心等待,因为我对编码还很陌生。
我的程序适用于输入2、4、8、16、32、64等等,因为所有这些都是1。但任何其他输入都不起作用
#include <iostream>
using namespace std;
struct node
{
node* ptr;
int data;
}start;
int main()
{
node *start=NULL;
int n;
cout<<"Enter the number of students : ";
cin>>n;
node *temp=new node;
temp->data=1;
temp->ptr=NULL;
start=temp;
for(int x=2;x<=n;x++)
{
node* temp1=new node;
temp1->data=x;
temp->ptr=temp1;
temp1->ptr=start;
temp=temp1;
}
node* temp2=start;
do
{
cout<<temp2->data<<" ";
temp2=temp2->ptr;
}while(temp2!=start);
cout<<endl;
//delete bigins here
temp2=start;
node* temp3=temp2->ptr;
do
{
temp2->ptr=temp3->ptr;
temp3->ptr=NULL;
delete temp3;
temp2=temp2->ptr;
temp3=temp2->ptr;
}while(temp2->ptr!=start);
temp2=start;
do
{
cout<<temp2->data<<" ";
temp2=temp2->ptr;
}while(temp2!=temp3);
cout<<endl;
}
我的程序适用于输入2、4、8、16、32、64等等,因为所有这些都是1。
这是一个很好的观察结果。事实上,答案离这里只有一小步之遥。
您有n
个候选项,每次选择1个。如果n
是x + 2^k
(具有最大可能的k(,则在x
步之后,您还有2^k
个候选者,行中的下一个候选者就是答案。所以答案是2x+1
。
1 2 3 4 5 6 7
^ ^ ^ |
removed |
answer
注:此练习可在《具体数学:计算机科学基础》中找到。我强烈推荐它。
问题在于核心循环:
do {
temp2->ptr=temp3->ptr;
temp3->ptr=NULL;
delete temp3;
temp2=temp2->ptr;
temp3=temp2->ptr;
} while (temp2->ptr!=start);
这个循环只遍历数据一次:当它到达第一组删除的末尾时停止,因为它在第一次返回start
时停止。这就是为什么你总是得到答案1,正如你所指出的,当列表长度是2的幂时,这个答案是正确的。
相反,它应该循环,直到只剩下一个node
,它将指向自己作为下一个node
。因此do ... while
循环的最后一行应该是:
} while (temp2->ptr != temp2)
很明显,世界已经发生了变化:我第一次听到这个谜题是关于海盗喝毒药来确定谁得到了宝藏!
要极大地简化您的解决方案,请实现"软删除"。在节点结构上放置一个名为"int deleted"的标志,并将其初始化为0。每次要删除节点时,只需将deleted=1设置即可。你的问题中的指针逻辑有问题,这消除了大部分问题。
在寻找下一个要删除的节点时,如果该节点已删除==1,则不要将其算作剩余节点之一,只需继续操作,直到找到第二个deleted=0的节点,并将其设置为1。
在这一点上,你甚至不需要一个循环列表,甚至不需要列表。您可以只使用值为0或1的int数组。如果你记下还有多少,那么只要你只剩下一个,你就可以停下来,否则你就必须遍历整个数组,以确保一个都没有。
这并没有那么快,因为你的列表永远不会变小,你会看到很多被删除的条目,但它要简单得多。
第二个do-while循环中有一个小错误(删除(。while语句在循环中迭代一次后强制终止循环,即,一旦循环回到起始节点,它就退出。您需要更改线路
while(temp2->ptr!=start);
至
while(temp2->ptr!=temp2);
另外,最后一个do-while循环似乎运行到了一个无限循环中,因为它上面的语句:
temp2 = start;
在删除过程中,您不会跟踪一旦删除元素1就会被删除的开始指针。因此temp2指向垃圾。拆下这根线也能解决这个问题。
- 仅显示链表的最后一个元素
- C++链表最后一个元素的迭代器?
- C++ 链表程序打印最后一个数据项 n 次
- 如何将自己的链表实现从存储整数更改为存储个人数据
- 链表一副牌,只出现51张牌,没有出现52张
- 链接列表中最后一项之后的项目是否为0
- 链表:最后一个指针不是NULL
- 最后在C++的链表中添加节点
- qsqlQuery 中的 next() 返回表中的最后一条记录
- 链表只打印添加新节点后的最后一个元素
- 选择是一种奇异的链表
- C++将节点添加到链表的开头一次后失败.其他方法也有问题
- 链表:无法访问最后一个节点,获取 R6010(C++、VS2010)
- 删除双向链表 (C++) 的最后一个节点
- 打印链表仅打印最后一个节点
- 链表在c++中从最后到第一显示
- 如何删除C++中添加到链表中的最后一个元素
- 删除单向链表最后一个元素的递归方法
- 最后一个人站着,使用了圆形链表
- 自定义 ostream 仅打印"<<"链的最后一串