只能用数组,不能用ArrayList之类的,有更优的方法么
//总共17人
int [] total = new int[17];
//报数值,从1开始
int claimNum = 1;
for (int i = 0; i < total.length; i++) {
total[i] = i+1;
}
int remainLength=total.length;
while(remainLength!=1){
for (int i = 0; i < total.length; i++) {
//出圈的人标示为0
if(total[i]!=0){
System.out.println("报数"+claimNum);
if(claimNum%3==0){
System.out.println("出圈,位置"+total[i]);
total[i]=0;
remainLength--;
}
claimNum++;
}
}
}
System.out.println("finish");
//总共17人
int [] total = new int[17];
//报数值,从1开始
int claimNum = 1;
for (int i = 0; i < total.length; i++) {
total[i] = i+1;
}
int remainLength=total.length;
while(remainLength!=1){
for (int i = 0; i < total.length; i++) {
//出圈的人标示为0
if(total[i]!=0){
System.out.println("报数"+claimNum);
if(claimNum%3==0){
System.out.println("出圈,位置"+total[i]);
total[i]=0;
remainLength--;
}
claimNum++;
}
}
}
System.out.println("finish");
//稍微改了下没深入思考, 去掉没用的报数信息
//去掉低效的%取模运算
//总共17人
int [] total = new int[17];
//报数值,从1开始
int claimNum = 1;
for (int i = 0; i < total.length; i++) {
total[i] = i+1;
}
int remainLength=total.length;
while(remainLength!=1){
for (int i = 0; i < total.length; i++) {
//出圈的人标示为0
if(total[i]!=0){
if(claimNum == 3){
System.out.println("出圈,位置"+total[i]);
total[i]=0;
remainLength--;
claimNum = 0; //清0计数
}
claimNum++;
}
}
}
System.out.println("finish");
System.out.println(josephus2(5));
} /**
* 计算约瑟夫问题,间隔 1 个的值,这个有数学解法,即:将最高位的 1 取出,将数值左移一位,
* 再将最高位的那个 1 添至最低位即可<br />
* 例如 1010 的约瑟夫间隔为 1 的值为 0101(5)。Concrete Mathematics 书中并未加 1,
* 那是由于其第一个从 0 开始的,如果从 1 开始时需要加 1<br />
* 算法参考:Concrete Mathematics 一书第一章最后部分
*
* @param count
* @return
*/
public static int josephus2(int count) {
int n = (count ^ leftOneBit(count)) << 1;
return (n | 1) + 1;
} /**
* 获得一个数最高位为 1 的值,比如 1111(15)的最高位值为 1000<br />
* 算法参考:Hacker's Delight 一书第三章
*
* @param num
* @return
*/
public static int leftOneBit(int num) {
for(int i = 0; i < 5; i++) {
num |= (num >> (1 << i));
}
return num - (num >>> 1);
}
}