最后一名男子站立,使用循环链表

时间:2013-05-13 09:54:12

标签: c++

问题:一家公司招聘候选人,让他们坐成一圈。 他们选择每一个候选人并离开圆圈(因此圆圈越来越小),直到只留下一个。 所以,如果有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人,他会站在哪里。 Ans:我试图制作一个你输入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;
}

4 个答案:

答案 0 :(得分:2)

  

我的程序适用于输入2,4,8,16,32,64等,因为所有这些都是1。

这是一个很好的观察。实际上,答案距离这里只是一小步。

您有n个候选人,每次选择1个。如果nx + 2^k(最大可能为k),则在x步后,您会留下2^k个候选人,并且该行中的下一位候选人就是答案。所以答案是2x+1

1 2 3 4 5 6 7
  ^   ^   ^ |
   removed  |
       answer

注意:此练习可在Concrete Mathematics: Foundation for Computer Science中找到。我强烈推荐它。

答案 1 :(得分:2)

问题在于核心循环:

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)

显然世界已经开始了:我第一次听到这个谜题是关于海盗喝毒药以确定谁得到了宝藏!

答案 2 :(得分:0)

大大简化您的解决方案,实施“软删除”。在你的节点结构上放一个名为“int deleted”的标志,并将其初始化为0.每次要删除一个节点时,只需设置deleted = 1.你的问题中的指针逻辑有问题,这就解决了大部分问题

当您正在寻找要删除的下一个节点时,如果节点已删除== 1,则不要将其计为其余节点之一,只需继续操作,直到找到第二个节点已删除= 0 ,并将其设置为1。

您甚至不需要循环列表,甚至此时也不需要列表。您可以使用值为0或1的整数数组。如果您仍然计算剩余数量,那么只要剩下一个,就可以停止,否则您将不得不遍历整个数组确保没有剩下的。

这不是那么快,因为你的列表永远不会变小,而且你正在查看大量已删除的条目,但它更简单。

答案 3 :(得分:0)

第二次执行while循环(删除)时出现一个小错误。 while语句在迭代一次之后强制循环终止,即,一旦它到达起始节点,它就退出。您需要更改行

while(temp2->ptr!=start);

while(temp2->ptr!=temp2);

最后一次while循环似乎遇到了无限循环,因为它上面的语句:

temp2 = start;

删除期间,您不会跟踪删除元素1后立即删除的开始指针。因此temp2指向垃圾。删除此行也应该解决这个问题。