题目: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
浙公网安备 33010602011771号