约瑟夫问题:
总共有n个小孩围成一个圈,编号从1到n且连续,从编号为s的小朋友开始报数,数到c的小孩出圈,下一个小孩继续从1开始报数,数到c的出圈......以此类推,直到所有人出圈,求依次出圈小孩的编号。
package sjjg;
public class Josephu {
public static void main(String[] args) {
CircleSingleLinkedList circleSingleLinkedList = new CircleSingleLinkedList();
circleSingleLinkedList.addChild(125);
// circleSingleLinkedList.list();
circleSingleLinkedList.circleGame(22, 125, 21);
}
}
class CircleSingleLinkedList {
private Child first = null;
public void addChild(int nums) {
if (nums < 1) {
System.out.printf("您输入的数量%d有误,请重新输入", nums);
return;
}
Child curchild = null;
for (int i = 1; i <= nums; i++) {
Child child = new Child(i);
if (i == 1) {
first = child;
first.setNext(first);
curchild = first;
}
curchild.setNext(child);
child.setNext(first);
curchild = child;
}
}
public void list() {
if (first == null) {
System.out.println("圈中没有小孩");
return;
}
Child curchild = first;
while (true) {
System.out.printf("小孩的编号:%d\n", curchild.getNo());
curchild = curchild.getNext();
if (curchild == first) {
break;
}
}
}
public void circleGame(int startNo, int nums, int countNums) {
if (startNo < 1 || first == null || startNo > nums) {
System.out.println("参数有误,不能开始游戏");
}
Child helper = first;
while (true) {
if (helper.getNext() == first) {
break;
}
helper = helper.getNext();
}
for (int i = 1; i < startNo; i++) {
first = first.getNext();
helper = helper.getNext();
}
while (true) {
for (int j = 1; j < countNums; j++) {
first = first.getNext();
helper = helper.getNext();
}
System.out.printf("出圈的小孩编号为%d\n", first.getNo());
helper.setNext(first.getNext());
first = first.getNext();
if (helper == first) {
System.out.printf("最后出圈的小孩编号为%d\n", first.getNo());
break;
}
}
}
}
class Child {
private int no;
private Child next;
public Child(int no) {
this.no = no;
}
public int getNo() {
return no;
}
public void setNo(int no) {
this.no = no;
}
public Child getNext() {
return next;
}
public void setNext(Child next) {
this.next = next;
}
}
e.g. s=22,n=125,c=21