剑指offer62. 圆圈中最后剩下的数字
0,1,···,n-1这n个数字排成一个圆圈,从数字0开始,每次从这个圆圈里删除第m个数字(删除后从下一个数字开始计数)。求出这个圆圈里剩下的最后一个数字。
例如,0、1、2、3、4这5个数字组成一个圆圈,从数字0开始每次删除第3个数字,则删除的前4个数字依次是2、0、4、1,因此最后剩下的数字是3。
限制:
1 <= n <= 10^5
1 <= m <= 10^6
思路:用f(n,m)表示
,每次删除第m个数字所剩下的那个数。那么第一次删除之后,变成
个数,删除的那个数是
,那么是从
开始删下一个数,映射关系就是从
,即最后剩余的那个数是
。两次剩余的那个数是相同的,所以有递推关系式
。
Java代码如下:
class Solution {
public int lastRemaining(int n, int m) {
if(n == 1) {
return 0;
}
return (lastRemaining(n-1,m) + m) % n;
}
}
NC132 环形链表的约瑟夫问题
编号为 1 到 n 的 n 个人围成一圈。从编号为 1 的人开始报数,报到 m 的人离开。
下一个人继续从 1 开始报数。
n-1 轮结束以后,只剩下一个人,问最后留下的这个人编号是多少?
数据范围:
进阶:空间复杂度,时间复杂度
思路:这里的编号是从1到n,由于涉及到对n取余操作,那么(f(n,m-1)+m)%n的结果是[0,n-1],必然不符合题意,所以需要进行-1,+1处理,即(f(n-1,m)+m-1)%n+1
Java代码如下:
import java.util.*;
public class Solution {
/**
*
* @param n int整型
* @param m int整型
* @return int整型
*/
public int ysf (int n, int m) {
// write code here
int x = 1;
for(int i = 2;i <= n;i++) {
x = (x + m - 1) % i + 1;
}
return x;
}
}