您的位置:首页 > Web前端

剑指Offer:圆圈中最后剩下的数字

2018-03-18 13:10 225 查看
0,1,……,n-1这n个数字排成一个圆圈,从数字0开始每次从这个圆圈里删除第m个数字。求出这个圆圈最后剩下的那个数字。

这是著名的约瑟夫环问题,下面提供两种解法。

经典解法:使用环形链表

自己创建一个环形链表比较麻烦,这里我使用LinkedList来模拟环形链表。但是LinkedList不是环形的,所有每当迭代器(iterator)扫描到链表尾部时要将它移到头部,从而实现环形。

实现代码:

private static int LastNumOfRing(int n,int m){
if(n<0|m<1){
return -1;
}
List<Integer> list = new LinkedList<Integer>();
//由于JAVA中对集合进行遍历时不能修改集合,所有我将要删除的元素暂时放在temp中,待遍历完再删除list中的元素
List<Integer> temp = new ArrayList<Integer>();
for(int i=0;i<n;i++){
list.add(i);
}
int count=1;
Iterator<Integer> iterator = list.iterator();
int size=list.size();
while(size>1){
if(iterator.hasNext()){
}else{
iterator = list.iterator();//回到开头
}
Integer num = iterator.next();
if(temp.contains(num)){
continue;
}
if(count==m){
temp.add(num);
count=1;
size--;
list.toString();
}else{
count++;
}
}
for (Integer integer : temp) {
list.remove(integer);
}
return list.get(0);
}


创新解法:找规律

首先我们定义一个函数f(n,m)表示每次在0~n-1中每次删除第m个数字最后剩下的那个数字。

经过复杂的推导(省略)我们可以得到以下递归式:



使用循环实现代码:

private static int LastNumOfRing(int n,int m){
if(n<0|m<1){
return -1;
}
int last=0;
for(int i=2;i<=n;i++){
last = (last+m)%i;
}
return last;
}


这种方法实现代码真的是太简洁了,Offer稳了!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息