剑指offer 62. 圆圈中剩下的数字(约瑟夫环问题)

剑指 Offer 62. 圆圈中最后剩下的数字 - 力扣(LeetCode) (leetcode-cn.com)

目录

运行结果

分析

删除第m个数字

序列重组

映射

递推关系

代码


运行结果

 

分析

删除第m个数字

初始序列:

0, 1, ..., n-1    (1)

我们把从序列(1)中按照规则不断删除第m个数字 最后剩下的数字记作f(n, m)

进行一次操作,我们删除掉的数字:k = (m-1)%n

剩余的序列:0, 1, ..., k-1, k+1, ..., n-1

序列重组

按照规则,下次从k+1开始计数,于是我们把该序列重组,得到:

k+1, ..., n-1, 0, 1, ..., k-1    (2)

该序列可以看作是把以下序列整体 % n 之后得到的序列
k+1, ..., n-1, n, n+1, ..., n+k-1

序列(2)有n-1项,我们把从该序列中不断按照规则删除第m个数字之后剩下的数字记作g(n-1, m)则:

f(n, m) == g(n-1, m)

映射

我们对序列(2)做一个映射,得到序列(3):

k+1    ->    0
...
n-1    ->    n-k-2
0      ->    n    ->    n-k-1
...
k-1    ->    n+k-1    ->    n-2


0,1,...,n-2    (3)

我们把这种映射记作p(x),则p(x) = (x - k - 1) % n

该映射的逆映射为:q(x) = (x + k + 1) % n

序列(3)有n-1项,且和序列(1)具有同样的形式,因此从序列(3)中按照规则不断删除第m个元素后剩下的数字为 f(n-1, m)

根据序列(2)和序列(3)之间的映射关系,我们可以得出:

g(n-1, m) == q( f(n-1, m) )

那么就有:

f(n, m) == q( f(n-1, m) )

因此我们就得到了:

递推关系

f(n, m)
= q( f(n-1, m) )
= ( f(n-1, m) + k + 1 ) % n
= ( f(n-1, m) + (m-1)%n + 1 ) % n
= ( f(n-1, m) + m ) % n

如果初始序列中只有一个元素0,那么按照规则,0就是最终剩余的元素,即:

f(1, m) = 0

根据递推关系,即可写出代码

代码

class Solution {
public:
	int lastRemaining(int n, int m) {
		int last = 0;
		for (int i = 2; i <= n; ++i) {
			last = (last + m) % i;
		}
		return last;
	}
};

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值