约瑟夫问题是个有名的问题:N个人围成一圈,从第一个开始报数,第M个将被杀掉,最后剩下一个,其余人都将被杀掉。
例如N=6,M=5,被杀掉的顺序是:5,4,6,2,3,1。
下面是我的实现代码及实现思路。
import java.util.ArrayList;
import java.util.List;
public class My_JOSEF {
/**
*
* 分析:
* 1、先根据具体人数生成一个List,并且每个值代表某人的编号。
* 2、计算将杀之人的index,将杀到的人移除出List。
* 3、最终结果是全部人死亡,所以循环List的长度次数2步骤杀人。
*
*/
public static final int N = 6; //定义人数
public static final int M = 5; //定义第M个人被杀
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
for(int i=1; i<=N; i++){
list.add(String.valueOf(i));
}
long begin = System.currentTimeMillis();
kill(list, M);
long end = System.currentTimeMillis();
System.out.println("My_JOSEF 此次任务所消耗毫秒数:" + (end - begin));
}
public static void kill(List<String> list, int M){
int size = list.size();
int index = 0;
for(int i=0; i<size; i++){
if((index + M) >= list.size()){
index = (index + M - 1) % list.size();
}else{
index = index + M - 1;
}
System.out.println("本轮被杀的人是 "+ (list.get(index)) +" 号");
list.remove(index);
index = index == list.size() ? 0 : index;
}
}
}
后面我又去百度百科查了下,根据百度百科的分析也尝试着实现了一下。
public class JOSEF_Demo {
/**
*
分析:
(1)由于对于每个人只有死和活两种状态,因此可以用布朗型数组标记每个人的状态,可用true表示死,false表示活。
(2)开始时每个人都是活的,所以数组初值全部赋为false。
(3)模拟杀人过程,直到所有人都被杀死为止。
*提示:该分析复制自百度百科 约瑟夫问题!
*
*/
public static final int N = 6; //定义人数
public static final int M = 5; //定义第M个人被杀
public static void main(String[] args) {
boolean[] arrs = new boolean[N];
long begin = System.currentTimeMillis();
kill(arrs, 0);
long end = System.currentTimeMillis();
System.out.println("JOSEF_Demo 此次任务所消耗毫秒数:" + (end - begin));
}
public static void kill(boolean[] arrs, int index){
for(int i = 0; i < arrs.length; i++){
int n = 0;
while(n < M){
if(!arrs[index]){
n++;
}
if(n != M){
index = (index == arrs.length - 1)? 0 : ++index;
}
}
arrs[index] = true;
System.out.println("本轮被杀的人是 "+ (index+1) +" 号");
}
}
}
总结:
两种实现方法在人数基数为6的时候,基本上都是0毫秒,1毫秒就能解决,相差不大,然后我把人数基数调到100万后,执行效率就很明显了,我自己的思路实现的代码花了大概60000ms,而根据百度百科的思路去实现的只用了14000ms多。另外值得一提的是在我实现的方式中,因为听说LinkedList在增删比较多情况下,会比ArrayList快,所以我尝试着把ArrayList换成LinkedList,花了几分钟都没跑完。这不得不让我重新再去研究下什么时候才适合使用LinkedList了呀。