丢手帕问题,约瑟夫问题(集合实现)
-
题目:
约瑟夫问题是个有名的问题:N个人围成一圈,从第一个开始报数,第M个将被杀掉,最后剩下一个,其余人都将被杀掉。例如N=6,M=5,被杀掉的人的序号为5,4,6,2,3。最后剩下1号。
-
思路:
网上有很多的解决方法,有用
链表
,用一个循环链表
来解决问题。但是,我的第一个想法是用集合
,集合的内部的实现,当然也是用上链表的思想,想着java
已经提供了方便的集合
,那为什么不用呢?而且,也不需要变成循环链表
这么复杂,只需要用一个flag
来标记,当到flag
到达最后的时候,再从头再来,就是了。 -
集合实现代码:
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
/*
* 题目:对手帕问题,约瑟夫问题
* N个人围成一圈,从第一个开始报数,第M个将被杀掉,然后从下一个开始报数,最后剩下一个,其余人都将被杀掉。例如N=6,M=5,
* 被杀掉的人的序号为5,4,6,2,3。最后剩下1号。
* 解题思路:
* 使用list集合,数到相应的位置就remove,
* 用flag来标记,到底删除哪一个,碰到末尾就从头开始数,并用余数来巧妙地得到该删除哪一个
*/
public class Main{
public static void main(String[] args){
Scanner jin=new Scanner(System.in);
Main main=new Main();
while(jin.hasNext()){
int N=jin.nextInt();
int M=jin.nextInt();
main.killLast(N, M);
}
}
public void killLast(int N,int M){
List<Integer> personList=new ArrayList<Integer>();
//初始化n个人围成一圈,初始化1~N
for(int x=0;x<=N;x++){
personList.add(new Integer(x));
}
int mod=-1;//初始化余数
int flag=1;//默认标记到第一个人
//判断杀掉哪一个人
while(personList.size()!=2){//默认从0开始数,为了对应1~N,所以最后跳出循环是有2个
flag+=(M-1);//将要标记杀掉的那个人
mod=flag%(personList.size()-1);//使flag永远在圈内人数范围内循环移动,personList.size()-1是因为要数当前的这个位置
if(mod==0)
flag=(personList.size()-1);//mod=0,刚好整除,flag标记到最后一位
else
flag=mod;
System.out.print(personList.remove(flag)+" ");
}
System.out.println();
System.out.println(personList.get(1));
}
}
-
链表实现代码
-
参考资料:
- 丢手帕问题 (约瑟夫问题)Java实现,此方法是用
循环链表
实现的。
- 丢手帕问题 (约瑟夫问题)Java实现,此方法是用