【从零单排之微软面试100题系列】18之约瑟夫环问题

原题参见july大神博客系列【微软面试100题】


题目描述:n个数字(0到n-1)排成一个圆圈,从0开始每次删除第m个数字。求剩下的最后一个数字。


分析思路:(本题亦见于《剑指offer》面试题45)

假设第一个删掉是元素k(其中k = (m-1)%n),那么下一轮将从剩下的n-1个元素删掉从元素k+1开始的第m个元素。若将元素k+1看成是第0个元素。

则存在映射:k+1 → 0,k+2 →1,...,n-1→n-k-2,0 →n-k-1,1→n-k,...,k-1→n-2(映射函数为p(x) = (x-k-1)%n)

如果用f(n,m)表示从0开始,每次在n个数字中删掉第m个数字最终留下的数字,那么f(n-1,m)就表示从0开始,每次在n-1个数字中删掉第m个数字最终留下的数字

于是存在关系式:f(n,m) = [f(n-1,m)+k+1]%n = [f(n-1,m) + m]%n. 又当n=1时,f(1,m) = 0.于是通过递归或迭代的方法都能求解出来。

(更深入阐述:假设最后留下的数字是1,即f(n,m)=1,那么删除第一个数后,重新将k+1看成是0,那么最后留下的数字仍是1,只不过通过映射,这个“1”变成了“n-k”,所以得通过逆映射把“n-k”变回“1”,于是有f(n,m) = [f(n-1,m)+k+1]%n = [f(n-1,m) + m]%n)

代码如下:

int Joseph(int n, int m)
{
	if( n < 1 || m < 1 )
		return -1
	int last = 0;
	for (int i = 2; i <= n; i++)
		last = (last + m)% i;
	return last;

}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值