剑指offer系列之45:圆圈中最后剩下的数字

来源:互联网 发布:linux 编译环境 编辑:程序博客网 时间:2024/06/05 10:30

题目描述:用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;    }}
0 0