@toc
一、题目
每年六一儿童节,牛客都会准备一些小礼物去看望孤儿院的小朋友,今年亦是如此。HF作为牛客的资深元老,自然也准备了一些小游戏。其中,有个游戏是这样的:首先,让小朋友们围成一个大圈。然后,他随机指定一个数 m,让编号为 0 的小朋友开始报数。每次喊到 m-1 的那个小朋友要出列唱首歌,然后可以在礼品箱中任意的挑选礼物,并且不再回到圈中,从他的下一个小朋友开始,继续 0 … m-1 报数 … 这样下去…直到剩下最后一个小朋友,可以不用表演,并且拿到牛客名贵的“名侦探柯南”典藏版(名额有限哦!!_)。请你试着想下,哪个小朋友会得到这份礼品呢?(注:小朋友的编号是从 0 到 n-1 )
如果没有小朋友,请返回 -1。
二、分析及代码
1. 环形链表模拟
(1)思路
最直接的方法是,基于环形链表模拟题中的圆圈,此时时间复杂度为 O(mn),空间复杂度为 O(n)。
(2)代码
public class Solution {
public int LastRemaining_Solution(int n, int m) {
if (n < 1)
return -1;
if (n == 1)
return 0;
ListNode head = new ListNode(0);
ListNode pre = head;
ListNode node = null;
for (int i = 1; i < n; i++) {
node = new ListNode(i);
pre.next = node;
pre = node;
}
node.next = head;
while (node.next != node) {
for (int i = 0; i < m - 1; i++)
node = node.next;
node.next = node.next.next;
}
return node.val;
}
}
class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}
(3)结果
运行时间:28ms,占用内存:9420k。
2. 递推公式
先数学归纳得到剩下数字的递推公式,具体过程可参照《剑指offer》书本,得到的公式为:
f(n,m)=0, n=1
f(n,m)=[f(n-1,m)+m]%n, n>1
结合递推公式,可通过递归或循环快速计算得到结果。
(2)代码
public class Solution {
public int LastRemaining_Solution(int n, int m) {
if (n < 1)
return -1;
int num = 0;
for (int i = 2; i <= n; i++)
num = (num + m) % i;
return num;
}
}
(3)结果
运行时间:18ms,占用内存:9204k。
三、其他
暂无。