1. 约瑟夫问题
约瑟夫问题是个有名的问题:N个人围成一圈,从第一个开始报数,第M个将被杀掉,最后剩下一个,其余人都将被杀掉。例如N=6,M=5,被杀掉的顺序是:5,4,6,2,3,1。
2. 思路分析
采用环形链表的方式,该链表中存储first结点与cur结点,分别表示第一个人与最后一个人,其中cur.next = first,即最后一个人指向第一个人。
采取循环的方式进行,设置计数器times,当计数器等于M时,将该结点出链表,出链表的操作为:first = first.next;cur.next = first;times++;当计数器不等于M时,执行的操作仅仅为将first与cur向后移动一位,即
first = first.next; cur = cur.next; times++。
3. 图解
times = 1:
如图,即为环形链表的初始状态,当进行报数时,将first以及cur分别向后移动,并且将times++;
times = 2:
如图,即为第一次移动之后的情况
times = M (即5)
到第五个人报数之后,执行以下操作: first向后移动 cur不动并且指向新的first,旧first节点next指向空,等待垃圾回收。
之后将times置为1,重新开始报数即可
4. 代码实现
package com.nansl.stucts.linkedList;
/**
* 环形链表解决约瑟夫问题
*/
public class Josephu {
private Boy first;
private Boy cur;
/**
* 无参构造器,底下有参的是为了测试环形链表
*/
public Josephu(){
}
public Josephu(int nums){
if (nums < 1){
System.out.println("男孩数量不能小于1");
return;