您的位置:首页 > 其它

孩子们的游戏(圆圈中最后剩下的数)

2018-03-21 21:10 239 查看

题目描述

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

【解决】

① 创建一个总共有 n 个结点的环形链表,然后每次在这个链表中删除第 m 个结点。

import java.util.ArrayList;
import java.util.List;

public class Solution {
public static void main(String[] args){
System.out.println(LastRemaining_Solution(0,0));
}
public static int LastRemaining_Solution(int n, int m) {
if (n < 1 || m < 1) return -1;
List<Integer> list = new ArrayList<>();
for (int i = 0;i < n;i ++){
list.add(i);
}
int index = 0;//要删除元素的位置
while(list.size() > 1){
int len = list.size();
for (int i = 1;i < m;i ++){//查找m-1次找到要删除的数的位置
index = (index + 1) % len;
}
list.remove(index);
}
return list.get(0);
}
}

② 更好一点的模拟

③ 找规律

首先我们定义一个关于 n 和 m 的方程f(n,m)时,表示每次在 n 个数字 0,1, … ,n-1中每次删除第 m 个数字最后剩下的数字。
在这 n个数字中, 第一个被删除的数字是(m-1)%n。为了简单起见,我们把(m- 1)%n 记为 k,那么删除k之后剩下的 n-1 个数字为 0,1,… ,k-1,k+1,… ,n-1,并且下一次删除从数字 k+1 开始计数。相当于在剩下的序列中, k+1 排在最前面,从而形成 k+1,... ,n- 1,0,I,… ,k-1 。该序列最后剩下的数字也应该是关于 n 和 m 的函数。由于这个序列的规律和前面最初的序列不一样(最初的序列是从 0 开始的连续序列),因此该函数不同于前面的函数,记为 f’(n-1,m)。最初序列最后剩下的数字 f(n, m)一定是删除一个数字之后的序列最后剩下的数字,即 f(n, m)=f’(n-1, m)。
接下来我们把剩下的这 n-1 个数字的序列 k-1, …,n-1,0,1,… ,k-1 做一个映射,映射的结果是形成一个从 0 到 n-2 的序列:





public class Solution {
public static void main(String[] args){
System.out.println(LastRemaining_Solution(6,3));
}
public static int LastRemaining_Solution(int n, int m) {
if (n < 1 || m < 1) return -1;
int last = 0;//指向最后一个要删除的数
for (int i = 2;i <= n;i ++){
last = (last + m) % i;
}
return last;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: