0,1,n-1这n个数字排成一个圆圈,从数字0开始,每次从这个圆圈里删除第m个数字。求出这个圆圈里剩下的最后一个数字。
例如,0、1、2、3、4这5个数字组成一个圆圈,从数字0开始每次删除第3个数字,则删除的前4个数字依次是2、0、4、1,因此最后剩下的数字是3。
示例 1:输入: n = 5, m = 3 输出: 3
示例 2:输入: n = 10, m = 17 输出: 2
计算公式: f(n, m) = (f(n-1, m) + m) % n
其中n表示一共有多少个数字,m表示数到第几个
递归
从数字0开始,每次从这个圆圈里删除第m个数字: 表示编号从0开始算起
public static void main(String[] args) {
System.out.println(lastRemaining(5, 3));
}
// 计算公式: f(n, m) = (f(n-1, m) + m) % n
// 递归
public static int lastRemaining(int n, int m) {
if (n == 1) return 0;
return (lastRemaining(n-1,m) + m) % n;
}
非递归
//
/*
* f(5, 3) = (f(4, 3) + 3) % 5
* f(4, 3) = (f(3, 3) + 3) % 4
* f(3, 3) = (f(2, 3) + 3) % 3
* ...
* f(2, 3) = (f(1, 3) + 3) % 2
* f(1, 3) = 0
*
*
* */
// 非递归
public static int lastRemainingF(int n, int m) {
int res = 0;
int begin = 2;
while (begin <= n) {
res = (res + m) % begin;
begin++;
}
// for (int i = 2; i <= n; i++) {
// res = (res + m) % i;
// }
return res;
}
如果改为从数字1开始,每次从这个圆圈里删除第m个数字: 表示编号从1开始算起,结果都是先计算编号从0开始的结果加上差值1就好
递归
public static void main(String[] args) {
System.out.println(lastRemaining(5, 3) );
}
// 计算公式: f(n, m) = (f(n-1, m) + m) % n
public static int lastRemaining(int n, int m) {
return f(n, m) + 1;// 编号从0开始算出的结果加上偏值1
}
public static f(int n, int m) {
if (n == 1) return 0;
return (lastRemaining(n-1,m) + m) % n;
}
非递归
public static int lastRemainingF(int n, int m) {
int res = 0;
int begin = 2;
for (int i = 2; i <= n; i++) {
res = (res + m) % i;
}
return res + 1; // 编号从0开始算出的结果加上偏值1
}