剑指 Offer 62. 圆圈中最后剩下的数字,约瑟夫环

剑指 Offer 62. 圆圈中最后剩下的数字icon-default.png?t=M666https://leetcode.cn/problems/yuan-quan-zhong-zui-hou-sheng-xia-de-shu-zi-lcof/

 约瑟夫问题

这个问题实际上是约瑟夫问题,这个问题描述是

N个人围成一圈,第一个人从1开始报数,报M的将被杀掉,下一个人接着从1开始报。如此反复,最后剩下一个,求最后的胜利者。

 

从8个人开始,每次杀掉一个人,去掉被杀的人,然后把杀掉那个人之后的第一个人作为开头重新编号

第一次C被杀掉,人数变成7,D作为开头,(最终活下来的G的编号从6变成3)
第二次F被杀掉,人数变成6,G作为开头,(最终活下来的G的编号从3变成0)
第三次A被杀掉,人数变成5,B作为开头,(最终活下来的G的编号从0变成3)
以此类推,当只剩一个人时,他的编号必定为0!(重点!)
 从最终活着的人编号的反推

f(n) 可由 f(n - 1)得到,f(n - 1)可由 f(n - 2)得到,……,f(2)可由 f(1)得到;因此,若给定 f(1) 的值,就可以递推至任意 f(n)。而F(1,m)的解 f(1) = 0 恒成立,即无论 m为何值,长度为 1 的数字环留下的是一定是数字 0。

动态规划解析:
状态定义: 设(i,m)的解为 dp[i] ;
转移方程: 通过以下公式可从 dp[i - 1]递推得到 dp[i] ;
dp[i] = (dp[i - 1] + m) %( i+1)

初始状态:(1,m)的解恒为 00,即 dp[1] = 0 ;
返回值: 返回(n,m)的解 dp[n];

class Solution:
    def lastRemaining(self, n,m):
        if n==1: return 0
        dp=[0]*n
        for i in range(1,n):
            dp[i]=(dp[i-1]+m)%(i+1)
        return dp[n-1]

根据状态转移方程的递推特性,无需建立状态列表 dpdp ,而使用一个变量 xx 执行状态转移即可。

 

class Solution:
    def lastRemaining(self, n,m):
        if n==1: return 0
        x=0
        for i in range(1,n):
            x=(x+m)%(i+1)
        return x

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值