问题
设编号为1,2,… n的n个小孩围坐一圈,约定编号为k(1<=k<=n)的小孩从1开始报数,数到m的小孩出列,它的下一位又从1开始报数,数到m的小孩又出列,依次类推,直到所有小孩出列为止,由此产生一个出队编号的序列。
提示
用一个不带头结点的循环链表来处理.Joseph问题:先构成一个有n个结点的单循环链表,然后由k结点起从1开始计数,计到m时,对应结点从链表中删除,然后再从被删除结点的下一个结点又从1开始计数,直到最后一个结点从链表中删除算法结束。
解题思路
第①步——创建单向循环链表
先创建第一个节点,让first指向该节点,并形成环形后面当我们每创建一个新的节点,就把该节点,加入到已有的环形链表中即可.
第②步——设计小孩出圈要素
需求创建一个辅助指针(变量) helper,事先应该指向环形链表的最后这个节点. 补充:小孩报数前,先让first和helper移动k-1次当小孩报数时,让first和helper指针同时的移动m -1次这时就可以将first指向的小孩节点出圈 first= first.next helper.next=first 原来first指向的节点就没有任何引用,就会被回收
代码实现
public class Joseph {
public static void main(String
[] args
) {
CircleSingleLinkedList circleSingleLinkedList
= new CircleSingleLinkedList();
circleSingleLinkedList
.addBoy(10);
circleSingleLinkedList
.countBoy(3, 3, 10);
}
}
class CircleSingleLinkedList {
private Boy first
= null
;
public void addBoy(int nums
) {
if (nums
< 1) {
System
.out
.println("nums的值不正确");
return;
}
Boy curBoy
= null
;
for (int i
= 1; i
<= nums
; i
++) {
Boy boy
= new Boy(i
);
if (i
== 1) {
first
= boy
;
first
.setNext(first
);
curBoy
= first
;
} else {
curBoy
.setNext(boy
);
boy
.setNext(first
);
curBoy
= boy
;
}
}
}
public void countBoy(int startNo
, int countNum
, int nums
) {
if (first
== null
|| startNo
< 1 || startNo
> nums
) {
System
.out
.println("参数输入有误, 请重新输入");
return;
}
Boy helper
= first
;
while (true) {
if (helper
.getNext() == first
) {
break;
}
helper
= helper
.getNext();
}
for(int j
= 0; j
< startNo
- 1; j
++) {
first
= first
.getNext();
helper
= helper
.getNext();
}
while(true) {
if(helper
== first
) {
break;
}
for(int j
= 0; j
< countNum
- 1; j
++) {
first
= first
.getNext();
helper
= helper
.getNext();
}
System
.out
.printf("小孩%d出圈\n", first
.getNo());
first
= first
.getNext();
helper
.setNext(first
);
}
System
.out
.printf("最后留在圈中的小孩编号%d \n", first
.getNo());
}
}
class Boy {
private int no
;
private Boy next
;
public Boy(int no
) {
this.no
= no
;
}
public int getNo() {
return no
;
}
public void setNo(int no
) {
this.no
= no
;
}
public Boy
getNext() {
return next
;
}
public void setNext(Boy next
) {
this.next
= next
;
}
}