约瑟夫问题:
假设有n个人手拉手围成一圈,顺时针开始报号,报到m的人出圈,然后继续往后报,报到m的人出圈,依次把所有报到m的人都踢出圈,问先后被踢出圈的那些人原来是圈内的几号,以及最后剩下的是几号?
算法思路:
1)用循环链表,报到m的节点从链表中删除,直到剩下最后一个节点,
2)用一个简单数组+模拟成圈
实现(下面的实现是基于第2种思路):
package com.algorithm.josephcircle;
public class BasicJoseph {
public static final int num = 7;
public static final int out = 3;
public static void main(String argv[]) {
boolean[] array = new boolean[num + 1];
for(int i = 1; i <= num; i++) {
array[i] = false;
}
int flag = 1;
int count = 1;
int index = 1;
while(true) {
if (array[flag] == false) {
if (index == num) {
System.out.println("the last is " + flag);
break;
}
if (count == out) {
array[flag] = true;
count = 1;
System.out.println("the " + index + " out is " + flag);
index++;
} else {
count++;
}
}
flag = (flag % num) + 1;
}
}
}
上面代码的关键在于使用数组记录数字是否别踢出,另外就是这些数字如何不断的循环,循环使用的结构如下:
while(true) {
flag = (flag % n) + 1
}