Josephus问题
/**
* Josephus问题。 N个人编号从1到N,从1号开始传递土豆。
* 经过m次传递后,清除当前拿着土豆的人, 由后面的人继续
* 传递m次,最后一个人为胜利者。
*/
public class SanDian6 {
public static void main(String[] args) throws Exception {
int n = 100; // 人数
int m = 5; // 传递次数
long start = System.currentTimeMillis();
getJphus(n, m);
long end = System.currentTimeMillis();
System.out.println(start + "-" + end + " = " + (end -start));
/**
* n = 1000; end - start = 1468804564005-1468804564035 = 30;
* n = 1,0000; = 1468804632861-1468804633193 = 332;
* n = 10,0000; = 1468804697639-1468804698848 = 1209;
* n = 100,0000; = 1468804795804-1468804806223 = 10419;
* n = 1000,0000; = 1468804924934-1468805035858 = 110924;
*/
}
/**
* @param n 人数
* @param m 传递次数
* @throws Exception
*/
private static void getJphus(int n, int m) throws Exception {
if(n == 0) throw new Exception("人数不能为空");
if(m < 0) throw new Exception("传递次数不能为负");
Node node = getNode(n);
//System.out.println(node);
int loop = 0; // 循环次数
Node mark = node;
Node markPre = null;
while(n != 1){
if(m == loop){
System.out.println("删除数字:" + mark.val);
// 当删除头结点时
if(markPre == null){
node = node.next;
mark = node;
}
// 删除尾节点
else if(mark.next == null){
markPre.next = null;
mark = node;
}
// 删除中间
else{
markPre.next = mark.next;
mark = mark.next;
}
n--;
loop = 0;
continue;
}
if(mark.next != null){
markPre = mark;
mark = mark.next;
}else{
markPre = mark.next;
mark = node;
}
loop++;
}
System.out.println(node);
}
/**
* create linkedNode of size is n.
* value is 1. 2. 3 ..... n
*/
private static Node getNode(int n) {
Node head = null;
Node mark = null;
for (int i = 1; i <= n; i++) {
Node temp = new Node(i, null);
if (i == 1) {
head = temp;
mark = temp;
}
mark.next = temp;
mark = mark.next;
// 形成环形链表
/*if(i == n)
mark.next = head;*/
}
return head;
}
}