算法1
(环形链表) O(n)
经典的解法, 用环形链表模拟圆圈。
创建一个总共有 n 个结点的环形链表,然后每次在这个链表中删除第 m 个结点。
Java 代码
class Solution {
public int lastRemaining(int n, int m) {
if (n < 1 || m < 1) {
return -1;
}
List<Integer> list = new LinkedList<>();
for (int i = 0; i < n; i++) {
list.add(i);
}
// 要删除元素的位置
int idx = 0;
// 开始计数的位置
int start = 0;
while (list.size() > 1) {
// 只要移动m-1次就可以移动到下一个要删除的元素上
for (int i = 1; i < m; i++) {
idx = (idx + 1) % list.size(); // 【A】
}
list.remove(idx);
// 确保idx指向每一轮的第一个位置
}
return list.get(0);
}
}
算法2
剑指offer的分析法
Java 代码
public static int lastRemaining2(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;
}
算法一中,start的那个变量没什么用