问题描述:
Josephus问题是下面的游戏:N个人编号从1到N,围坐成一个圆圈。从1号开始传递一个热土豆。经过M次传递后拿着热土豆的人被清除离座,围坐的圆圈紧缩,由坐在被清除的人后面的人拿起热土豆继续进行游戏。最后剩下的人取胜。
提供两种方案
package com.light.springboot.algorithm;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
/**
* Josephus问题是下面的游戏:N个人编号从1到N,围坐成一个圆圈。从1号开始传递一个热土豆。
* 经过M次传递后拿着热土豆的人被清除离座,围坐的圆圈紧缩,由坐在被清除的人后面的人拿起热土豆继续进行游戏。最后剩下的人取胜。
* @author qiaozhong
*/
public class Josephus {
/**
* 方案一:通过循环找list下标进行删除的方法解决约瑟夫问题
* @param person
* @param num
* @return
*/
public static String josephus(ArrayList<String> person, int num){
int i=0;
while(person.size() > 1){
//循环num次,确定i
for(int j=0; j < num; j++){
i++;
}
//当i大于当前总人数时,i减去总人数,使i小于总人数
while(i >= person.size()){
i = i - person.size();
}
person.remove(i);
}
return person.get(0);
}
/**
* 方案二:通过list的迭代器iterator解决约瑟夫问题,速度更快
* @param person
* @param num
* @return
*/
public static String iteratorJosephus(ArrayList<String> person, int num){
Iterator<String> iterator = person.iterator();
int count = 0;
while (person.size()>1) {
//步骤1:如果到链表尾部,就重新获取迭代器,以重头开始
if(!iterator.hasNext()){
iterator = person.iterator();
}
//步骤2:只要没有到链表结尾,就一直循环查下一个元素
while(iterator.hasNext() && count++ <= num){
iterator.next();
}
//步骤3:上边的while结束有两种可能,一种是count循环了num次,那么count++应该大于num,此种情况该删除当前元素
//另一种是查找到了链表尾部,此种情况不删除当前元素,应该回到步骤1重新执行iterator = person.iterator()继续查找
if (count > num) {
count = 0;
iterator.remove();
}
}
return person.get(0);
}
//测试两种方案效率
public static void main(String args[]){
ArrayList<String> person = new ArrayList();
for (int i = 0; i < 800000; i++) {
person.add(String.valueOf("第" + (i+1) + "位客人"));
}
long start = new Date().getTime();
System.out.println(josephus(person, 7) + "获胜!");
System.out.println("方案一消耗时间:" + (new Date().getTime() - start));
long iteratorStart = new Date().getTime();
System.out.println(iteratorJosephus(person, 7) + "获胜!");
System.out.println("方案二消耗时间:" + (new Date().getTime() - iteratorStart));
}
}
测试结果:
第194525位客人获胜! 方案一消耗时间:43501 第194525位客人获胜! 方案二消耗时间:1
分析:
方案一:我们的代码设计部分,我们每次调用remove时,都重新遍历了一遍表,调用n次remove,消耗时间为O(N2)。
方案二:通过迭代器能够有效地利用List的删除效率高的特性。因为迭代器的时间是O(1),迭代器的remove时间也是O(1),整体的运行时间理论上是O(N)。
原文:https://www.cnblogs.com/gllegolas/p/13307013.html