携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第14天,点击查看活动详情
Leetcode : leetcode-cn.com/problems/yu…
GitHub : github.com/nateshao/le…
剑指 Offer 62. 圆圈中最后剩下的数字
题目描述 :0,1,···,n-1这n个数字排成一个圆圈,从数字0开始,每次从这个圆圈里删除第m个数字(删除后从下一个数字开始计数)。求出这个圆圈里剩下的最后一个数字。
例如,0、1、2、3、4这5个数字组成一个圆圈,从数字0开始每次删除第3个数字,则删除的前4个数字依次是2、0、4、1,因此最后剩下的数字是3。
难度:简单
示例 1:
输入: n = 5, m = 3
输出: 3
示例 2:
输入: n = 10, m = 17
输出:
Go
func lastRemaining(n int, m int) int {
f := 0
for i := 2; i <= n; i++ {
f = (f+m)%i
}
return f
}
利用公式法:f[n] = (f[n-1] + k) mod n,或使用循环链表实现
来吧,一图胜千言。如下图所示,为 n = 5 , m = 3 时的状态转移和对应的模拟删除过程。
复杂度分析:
- 时间复杂度 O(n): 状态转移循环 n - 1 次使用 O(n) 时间,状态转移方程计算使用 O(1) 时间;
- 空间复杂度 O(1) : 使用常数大小的额外空间;
package com.nateshao.sword_offer.topic_49_lastRemaining;
/**
* @date Created by 邵桐杰 on 2022/2/24 21:51
* @微信公众号 千羽的编程时光
* @个人网站 www.nateshao.cn
* @博客 https://nateshao.gitee.io
* @GitHub https://github.com/nateshao
* @Gitee https://gitee.com/nateshao
* Description:
*/
public class Solution {
public static void main(String[] args) {
int i = lastRemaining(5, 3);
System.out.println("i = " + i);
}
public static int lastRemaining(int n, int m) {
int x = 0;
for (int i = 2; i <= n; i++) {
// i 个人时删除数的索引等于 i-1 个人时删除数的索引+k(再对i 取余)
x = (x + m) % i;
}
return x;
}
}