牛客刷题之圆圈中最后剩下的数

    科技2022-07-29  109

    题目描述

    每年六一儿童节,牛客都会准备一些小礼物去看望孤儿院的小朋友,今年亦是如此。HF作为牛客的资深元老,自然也准备了一些小游戏。其中,有个游戏是这样的:首先,让小朋友们围成一个大圈。然后,他随机指定一个数m,让编号为0的小朋友开始报数。每次喊到m-1的那个小朋友要出列唱首歌,然后可以在礼品箱中任意的挑选礼物,并且不再回到圈中,从他的下一个小朋友开始,继续0…m-1报数…这样下去…直到剩下最后一个小朋友,可以不用表演,并且拿到牛客名贵的“名侦探柯南”典藏版(名额有限哦!!_)。请你试着想下,哪个小朋友会得到这份礼品呢?(注:小朋友的编号是从0到n-1) 如果没有小朋友,请返回-1

    牛客链接:

    https://www.nowcoder.com/practice/f78a359491e64a50bce2d89cff857eb6?tpId=13&&tqId=11199&rp=1&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking

    解题思路:

    方法一,用循环链表模拟圆圈 方法二,采用数学推导-》约瑟夫环问题

    参考链接:

    https://blog.csdn.net/u013050857/article/details/70918064

    代码一:

    class Solution { public: struct pNode { int value; struct pNode* next; }; int LastRemaining_Solution(int n, int m) { if(n==0 || m==0) return -1; pNode* pHead = (pNode*)malloc(sizeof(pNode)); pHead->value = 0; pNode* pTemp = pHead; //建立链表 for(int i=1; i<n; i++) { pNode* pLast = (pNode*)malloc(sizeof(pNode)); pLast->value = i; pTemp->next = pLast; pLast->next = NULL; pTemp = pLast; } //使链表成为循环链表 pTemp->next = pHead; pTemp = pHead; int count=0; while(pTemp->next != pTemp) { count++; //删除第m个数,同时删除该链表节点 if(count == m-1) { count=0; pNode* pDelete; pDelete = pTemp->next; pTemp->next = pTemp->next->next; free(pDelete); pDelete = NULL; } pTemp = pTemp->next; } return pTemp->value; } };

    代码二: 第二种方法的递归解法

    class Solution { public: int LastRemaining_Solution(int n, int m) { if(n==0 || m==0) return -1; if(n==1) return 0; if(m==1) return n-1; return (LastRemaining_Solution(n-1,m)+m)%n; } };

    代码三: 第二种方法的非递归解法

    class Solution { public: int LastRemaining_Solution(int n, int m) { if(n==0 || m==0) return -1; if(n==1) return 0; if(m==1) return n-1; int last = 0; for(int i=2; i<=n; i++) { last = (last+m)%i; } return last; } };

    注意: 链表的遍历和删除 数学计算规律

    Processed: 0.010, SQL: 8