题目描述 设置编号为 1,2,3,…,n 的 n 个小孩围坐一圈,约定编号为 k(1=k=n)的小孩从 1 开始 报数,当数到 m 时对应的那个小孩出列。然后它的下一位又从 1 开始报数,当数到 m 时
题目描述
设置编号为 1,2,3,…,n 的 n 个小孩围坐一圈,约定编号为 k(1<=k<=n)的小孩从 1 开始 报数,当数到 m 时对应的那个小孩出列。然后它的下一位又从 1 开始报数,当数到 m 时对应的小孩 又出列,以次类推,直到所有小孩出列为止,由此产生一个出队编号的序列。
例如,上图中从编号为 2 的小孩从 1 开始报数,每次数到 3 时对应的那个小孩就出列,最后得 到的出队编号就是:4、7、10、3、8、2、9、6、1、5。
/**
* @Author yqq
* @Date 2022/05/06 17:36
* @Version 1.0
* 环形单链表的约瑟夫问题
*/
public class JosephTest {
public static void main(String[] args) {
//创建一个环形链表
Node lastNode = new Node(10);
Node node9 = new Node(9,lastNode);
Node node8 = new Node(8,node9);
Node node7 = new Node(7,node8);
Node node6 = new Node(6,node7);
Node node5 = new Node(5,node6);
Node node4 = new Node(4,node5);
Node node3 = new Node(3,node4);
Node node2 = new Node(2,node3);
Node headNode = new Node(1,node2);
lastNode.next = headNode;
joseph(headNode,lastNode,10,2,3);
}
/**
* 解决环形单链表的约瑟夫问题
* @param headNode 首节点
* @param lastNode 尾结点
* @param size 节点个数
* @param start 从编号为start的节点报数
* @param count 每次数几下
*/
public static void joseph(Node headNode,Node lastNode,int size,int start,int count){
//处理不合法的情况
//处理headNode为null的情况
if (headNode == null)
throw new NullPointerException("headNode is null:" + headNode);
//处理start和count不合法的情况
if (start < 1 || start > size || count <1)
throw new IllegalArgumentException("参数不合法");
//设置编号为start的节点开始报数,并且使用headNode指向该节点
//把headNode和lastNode往后移动start-1次
for (int i = 0; i < start - 1; i++) {
headNode = headNode.next;
lastNode = lastNode.next;
}
//定义一个循环,用于循环的执行报数操作
while (size != 0){//如果size等于0,则停止报数
//执行报数操作,也就是找到需要出圈的小孩,使用headNode节点指向需要出圈的节点
//把headNode和lastNode往后移动count-1次
for (int i = 0; i < count - 1; i++) {
headNode = headNode.next;
lastNode = lastNode.next;
}
//需要出圈的节点编号,也就输出headNode保存的数据值
System.out.print(headNode.data+"、");
//实现小孩的出圈操作,也就是把headNode从环形单链表中删除
//获得删除节点的后一个节点
Node nextNode = headNode.next;
//设置lastNode的next为nextNode
lastNode.next = nextNode;
//设置headNode的next值为null
headNode.next = null;
//更新size的值
size --;
//设置headNode指向nextNode
headNode = nextNode;
}
}
/**
* 节点类
*/
private static class Node{
/**
* 用于保存节点中的数值
*/
private Object data;
/**
* 用于保存下一个节点的地址值
*/
private Node next;
/**
* 专门为data做初始化的工作
* @param data
*/
public Node(Object data) {
this.data = data;
}
/**
* 专门为data和next做初始化的工作
* @param data
* @param next
*/
public Node(Object data, Node next) {
this.data = data;
this.next = next;
}
}
}