有个游戏是这样的:⾸先,让 n 个⼩朋友们围成⼀个⼤圈,⼩朋友们的编号是0~n-1。然后,随机指定⼀个数 m ,让编号为0的⼩朋友开始报数。每次喊到 m-1 的那个⼩朋友要出列唱⾸歌,然后可以在礼品箱中任意的挑选礼物,并且不再回到圈中,从他的下⼀个⼩朋友开始,继续 0... m-1报数....这样下去....直到剩下最后⼀个⼩朋友,可以不⽤表演,并且拿到⽜客礼品,请你试着想下,哪个⼩朋友会得到这份礼品呢?
示例
输⼊:5,3
输出:2
通过布尔数组标记小朋友的出局状态
public class Solution {
public int lastRemaining(int n, int m) {
if (n 1) {
// 如果当前小朋友未出局,参与报数
if (!out[index]) {
step++;
// 报到m-1的小朋友出局
if (step == m) {
out[index] = true; // 标记出局
count--; // 剩余人数减1
step = 0; // 重置计数器
}
}
// 移动到下一个位置(循环)
index = (index + 1) % n;
}
// 找到最后一个未出局的小朋友
for (int i = 0; i
使用循环链表模拟小朋友围成的圈,将小朋友存入链表,循环删除第m个元素
public class Solution {
public int lastRemaining(int n, int m) {
if (n list = new LinkedList();
// 初始化链表,存入所有小朋友编号
for (int i = 0; i 1) {
// 计算要删除的位置:(当前索引 + m-1) % 当前大小
index = (index + m - 1) % list.size();
list.remove(index);
// 删除后index自动指向下一个元素,不需要移动
}
return list.get(0);
}
}
分析每次被删除的数字规律,直接计算出最后的数字,不需要模拟
F(N,M) = ( F(N−1,M) + M ) % N
递推公式的推导过程:
示例验证(n=5, m=3):
原始编号: 0, 1, 2, 3, 4
第一次删除编号2 → 剩余: 0, 1, 3, 4
重新编号: 3→0, 4→1, 0→2, 1→3
f(5,3) = (f(4,3) + 3) % 5
public class Solution {
public int LastRemaining_Solution(int n, int m) {
if (n
将递归转为迭代,避免栈溢出风险,是生产环境的最佳选择
public class Solution {
public int lastRemaining(int n, int m) {
if (n
本文来自在线网站:seven的菜鸟成长之路,作者:seven,转载请注明原文链接:www.seven97.top
登录查看全部
参与评论
手机查看
返回顶部