我思故我在系列—数据结构面试题NO.18(题目搜集整理者JVLY,非常感谢!!)

       那些知道自己去哪儿,知道自己该干什么的人总能很好地利用环境,在前进路上不论遇到什么,他们都能灵活周转,向着目标更进一步。他们明白自己想干什么,也愿意作出努力。

                                                    ——摘自 奥格.曼狄诺《羊皮卷》

第18 题:
题目:n 个数字(0,1,…,n-1)形成一个圆圈,从数字0 开始,每次从这个圆圈中删除第m 个数字

(第一个为当前数字本身,第二个为当前数字的下一个数字)。当一个数字删除后,从被删除数字的下一个继续删除第m 个数字。求出在这个圆圈中剩下的最后一个数字。

方法1:单链表:

typedef struct node
{
    int data;
    struct node *next;
}Lnode,*Linklist;

Linklist Create_link()
{
    Linklist H,s,p;
    s=p=NULL;
    int i=0;
 int number;

    H=(Linklist)malloc(sizeof(struct node));
    H->next=NULL;
    printf("input number of person:number=");
    scanf("%d",&number);
    while(i<number)
    {
        i++;
        s=(Linklist)malloc(sizeof(Lnode));
        s->data=i;
        s->next=NULL;
          if(H->next==NULL)
            H->next=s;
        else
            p->next=s;
        p=s;//p始终指向最后一个节点;

    }
    p->next=H->next;
    return H;
}


Lnode* findlast(Linklist H)
{

     int num=1;
     int m;
     printf("input number of the quit:m=");
     scanf("%d",&m);
     if(H==NULL)
     {
         exit(0);
     }
     Lnode* p=H->next;/*指向H->next 而非  H*/
     Lnode* temp=p;
     while(p!=p->next)/*圆圈中不止一个数据*/
     {

         if(num==m-1)/*删除一m个节点,必须先找到第 m-1个节点*/
            {
              temp=p->next;
              p->next=temp->next;
              printf("free node :%4d\n",temp->data);
              free(temp);
              temp=NULL;
              num=1;
              p=p->next;
            }
         p=p->next;
         num++;
     }
     return p;
}


int main(int argc,char* argv[])
{
    Linklist H1=NULL;
    Lnode* pnode;
    H1=Create_link();
    pnode=findlast(H1);
    printf("the last node is %d\n",pnode->data);

    return 1;

}


方法2:/*删除数字后再从头开始计数*/

int LastRemaining_Solution2(int n, unsigned int m)
{
   if(n <= 0 || m < 0)
          {
         return -1;
          }

   int i;
   int lastinteger = 0;
   for (i = 2; i <= n; i ++)
       {
       lastinteger = (lastinteger + m) % i;
       }
   return lastinteger;
}

int main(int argc,char* argv[])
{
    int last;
    last=LastRemaining_Solution2(10, 3);
    printf("lastone :%d\n",last);
    return 1;
}


方法3:

#include <stdio.h>
#include <stdlib.h>
int main()
{
  int i,k,m,n,num[50];
  int* p=num;
  printf("input number of person:n=");
  scanf("%d",&n);
  printf("input number of the quit:m=");
  scanf("%d",&m);
  for(i=0;i<n;i++)
       {
        *(p+i)=i+1;
       }

   i=0;
   k=0;
  while(m<n-1)
      {
      printf("m=%d\n",m);

    if(*(p+i)!=0)   //若p指向的数字还未被删除,还有效,计数k++
          {
          k++;
          }
      if(k==m)/*将踢出的数值设置为0*/
                   {
             printf("delete value=%d\n",*(p+i));
         *(p+i)=0; //退出,对应的数组元素置为0
         k=0;
         m++;
                   }
   i++;
     if(i==n)//一次数组遍历完,从头开始再次遍历;
           {
         i=0;
            }
    }

  while(*p==0)
     {
      p++;
      }

  printf("The last one is NO.%d\n",*p);
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值