剑指offer第二版(Python3)--面试题62 : 圆圈中最后剩下的数字

第2章 面试需要的基础知识

第3章 高质量的代码

第4章 解决面试题的思路

第5章 优化时间和空间效率

第6章 面试中的各项能力

  面试题62 : 圆圈中最后剩下的数字
  面试题64 : 求1+2+3+…+n

第7章 两个面试案例


题目描述

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

解题思路
  实际上就是动态规划,只是这个递推式太难找了。

f(n)表示长度为n的序列,删除n-1次,最后留下元素的序号;

则f(n-1)表示长度为n-1的序列,删除n-2次,最后留下元素的序号;

我们知道 f(n)第一次删(m-1)%n,留下以((m-1)%n + 1)%(n-1)开头,长n-1的序列;

而f(n-1)留下元素的序号以0开头,因此两者的序号相差m个距离 f(n) = (f(n-1) + m) % n

具体可看LeetCode题解
这题是约瑟夫环问题,推荐博客约瑟夫环问题详解
实战

class Solution:
    def LastRemaining_Solution(self, n, m):
        # write code here
        # n表示序列长度
        if n < 1 or m < 1:
            return -1
        
        last = 0
        for i in range(2, n+1):
            last = (last + m) % i
        return last

代码中循环为什么是从2到n呢?不应该是从n到2吗?
从递推式 f(n) = (f(n-1) + m) % n 可知,我们是已知 f(n-1) 求解 f(n)的。显然已知条件是 f(1) = 0,从已知条件推导 f(2),逐步递推就得到最后的 f(n)。
DP算法的特点是分析问题的顺序和求解顺序相反。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值