题目:0,1...n-1这n个数字排成一个圆圈,从数字0开始每次从这个圆圈里删除第m个数字。求出这个圆圈里剩下的最后一个数字。

 方法一:

import java.util.ArrayList;

public class Solution{
    public static int lastRemaining(int n,int m){
        if(n<1||n<1){
            return -1;
        }
        ArrayList<Integer> list=new ArrayList<Integer>();
        for(int i=1;i<=n;i++){
            list.add(i);
        }
        //移除的数字的下标
        int idx=0;
        while(list.size()>1){
            idx=(idx+m-1)%list.size();
            //System.out.println(list.get(idx));
           list.remove(idx);
        }
        return list.get(0);
    }

    public static void main(String[] args){
        int lastNumber=lastRemaining(12,3);
        System.out.println(lastNumber);
    }
}

方法二:

       定义一个关于n和m的方程f(n,m),表示每次在n个数字0,1,...,n-1中每次删除第m个数字最后剩下的数字。第一个删除的数字是(m-1)%n,记为k,那么删除k之后,形成新的序列k+1,...,n-1,0,1,...,k-1。该序列的规律和前面最初的序列不一样(最初的序列是从0开始的连续序列),记为f'(n-1,m)。最初序列最后剩下的数字f(n,m)一定是删除一个数字之后的序列最后剩下的数字,即f(n,m)=f'(n-1,m)。

       把映射定义为p,则p(x)=(x-k-1)%n。它表示如果映射前的数字是x,那么映射后的数字是(x-k-1)%n。该映射的逆映射是p-1(x)=(x+k+1)%n。用于映射之后的序列和最初的序列具有同样的形式,即都是从0开始的连续序列,因此仍然可以用函数f来表示,记为f(n-1,m)。f'(n-1,m)=p-1[f(n-1,m)]=[f(n-1,m)+k+1]%n,把k=(m-1)%n代入得到f(n-m)=f'(n-1,m)=[f(n-1,m)+m]%n。

public class Solution{
    public static int lastRemaining(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;
    }

    public static void main(String[] args){
         int index=lastRemaining(12,3);
         System.out.println(index+1);
    }
}

 

 posted on 2018-12-04 22:42  会飞的金鱼  阅读(261)  评论(0)    收藏  举报