题目描述:用0,1,…,n-1,这n个数字排成一个圆圈,从数字0开始每次从这个圆圈里删除第m个数字,求出这个圆圈里剩下的最后一个数字。(抽象建模能力)
思路1:经典的解法,用环形链表模拟圆圈,可以创建一个总共有n个节点的环形链表,然后每次在这个链表中删除第m个节点。
思路2:把这n个整数做成一个环,当数到哪个数的时候就把那个数移除,并从下一个数重新开始数。所已基本思路是:使用数组模拟环,当当前的元素的值n相等的时候,就回到第一个位置重新遍历,每次当前元素的移动都伴随计步器的增加(每次增加1),当步数等于m的时候,则把当前元素的设为-1,表示已被删除,并重新设置计步器的值为0,还需要把n的值减小1,表示数组中的元素被移除了一个。使用数组来模拟环。
public class LastRemainingNumber {
public int LastRemaining_Solution2(int n, int m) {
if (n < 1 || m < 1)
return -1;
int[] a = new int[n];
//当前遇到的对象
int cur = -1;
//计步器
int count = 0;
int num = n;
while (num > 0) {
//移动到上次被删除元素的下一个元素
cur++;
//当遇到最后一个数的时候,从开头重新计算
if(cur == n) cur = 0;
//如果遇到了上次被删除的对象,则跳过该对象
if(a[cur] == -1)
continue;
//计步器加1
count++;
if(count == m){
//把当前元素标记为已删除
a[cur] = -1;
//计步器重新复位
count = 0;
num--;
}
}
return cur;
}
}
思路3:根据规律得到如下解法,参考剑指offer书上的解法。
public class Solution {
public int LastRemaining_Solution(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;
}
}