前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >剑指Offer题解 - Day55

剑指Offer题解 - Day55

作者头像
chuckQu
发布2022-08-19 11:05:29
1220
发布2022-08-19 11:05:29
举报
文章被收录于专栏:前端F2E

剑指 Offer 62. 圆圈中最后剩下的数字

力扣题目链接[1]

0,1,···,n-1这n个数字排成一个圆圈,从数字0开始,每次从这个圆圈里删除第m个数字(删除后从下一个数字开始计数)。求出这个圆圈里剩下的最后一个数字。

例如,0、1、2、3、4这5个数字组成一个圆圈,从数字0开始每次删除第3个数字,则删除的前4个数字依次是2、0、4、1,因此最后剩下的数字是3。

「示例 1:」

代码语言:javascript
复制
输入: n = 5, m = 3
输出:3

「限制:」

  • 1 <= n <= 10^5
  • 1 <= m <= 10^6

思路:

首先考虑使用暴力法进行题解。假定0~n-1的是循环链表,那么我们只需要每次移动指针m次,将当前节点删除,然后重复动作。最终当链表只剩下一个节点时,直接返回即可。

此做法需要的时间复杂度是O(mn) ,由题目限制可以看出,此时间复杂度是不可以接受的。而且本方法无法通过提交,会超时。因此不考虑此方法。

动态规划

本题是著名的 “约瑟夫环” 问题,可使用 「动态规划」 解决。

代码语言:javascript
复制
/**
 * @param {number} n
 * @param {number} m
 * @return {number}
 */
var lastRemaining = function(n, m) {
    let x = 0;
    for (let i = 2; i <= n; i++) {
        x = (x + m) % i;
    }
    return x;
};
  • 时间复杂度 O(n)。
  • 空间复杂度 O(1)。

分析:

我们假设[n,m]圆圈的最终解为f(n),那么[n-1, m]圆圈的解就是f(n - 1)。直到[1, m]圆圈的解为f(1)

对于初始状态[n,m],删掉第m个数字后,就得到一个n-1的圆圈。因为有可能m > n,因此删除掉的数字是(m - 1)%n。而下一轮的第一个数字就会从m%n开始。

此时,m%n 所代表的就是第一轮中的第一位数字0。可以看出,第一位数字的递推公式为x →(x + m %n)%n

最终,得出动态转移方程:

代码语言:javascript
复制
f(n) = (f(n - 1) + m%n)%n = (f(n - 1) + m)%n

对于初始值[1, m],也就是圆圈里只有1个数字,最终返回的就是0。所以f(1) = 0

总结

本题考查动态规划。约瑟夫环的问题是经典的数学问题,部分同学包括我在内,可能都不太记得该问题。而且动态方程也比较难归纳,难度系数中级。

复杂度方面,n-1 次循环需要时间为O(n) ,声明变量占用常数级别的空间。

参考资料

[1]

力扣题目链接: https://leetcode-cn.com/leetbook/read/illustration-of-algorithm/oxrkot/

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-03-15,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 前端F2E 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 剑指 Offer 62. 圆圈中最后剩下的数字
    • 动态规划
      • 总结
        • 参考资料
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档