例题:
17世纪的法国数学家加斯帕在《数目的游戏问题》中讲的一个故事,15个教徒和15个非教徒在深海上遇险,必须将一半的人投入海中,其余的人才能幸免于难,于是想了一个办法,30个人围成一个圆圈,从第一个人开始依次报数,每数到第九个人,就将他扔入大海,如此循环进行,直到仅剩余15个人为止。问怎样排法,才能使每次投入大海的都是非教徒。
解析:题目中30个人围成一圈,可以用一个循环的链来表示,使用结构数组来构成一个循环链。结构中有两个成员,其一为指向下一个人的指针,以构成环形的链;其二为该人是否被扔下海的标记,为1表示还在船上。从第一个开始对还未扔下海的人进行计数,每数到9时,将结构中的标记改为0,表示该人已被扔下海了。这样循环计数,直到有15个人被扔下海为止。
还有一种办法:使用一个Boolean数组来模拟,非教徒站的位置为false,教徒站的位置为true。一开始,所有的位置都为true,每数到9时,则自动将true设为false,如果该位置已经为false,则设置下一个true位置为false,如果已经循环到底,则重新开始。
public class Solution {
private static class Node{
int val;
boolean flag;
Node next;
public Node(int val){
this.val = val;
this.flag = false;
}
}
public int LastRemaining_Solution(int n, int m) {
if(n==0||m==0)
return -1;
Node pHead = new Node(0);
Node first = pHead;
for(int i=1;i<n;i++){
Node node = new Node(i);
first.next = node;
first = first.next;
}
first.next = pHead;
for(int i=0;i<n-1;i++){
int count =0;
while(count<m-1){
if(!pHead.flag){
count++;
pHead = pHead.next;
}else{
pHead = pHead.next;
}
}
if(!pHead.flag){
pHead.flag = true;
while(pHead.flag){
pHead = pHead.next;
}
}else{
while(pHead.flag){
pHead = pHead.next;
}
pHead.flag = true;
while(pHead.flag){
pHead = pHead.next;
}
}
}
while(pHead.flag){
pHead = pHead.next;
}
return pHead.val;
}
}