单向循环链表解决小孩出圈问题java实现
/**
* 构建一个单向的环形链表思路
* 1.先创建第一个节点,让first指向该节点,并形成环形
* 2.后面每创建一个节点,就把该节点加入到已有的环形链表中
* <p>
* 遍历环形链表
* 1.先让一个辅助指针(变量)cur,指向first节点
* 2.然后通过一个while循环遍历该环形链表即可 cur,next = first结束。
*
* @auther gaowenbin
* @create 2021-03-28-9:20
*/
public class Josepfu {
public static void main(String[] args) {
CircleSingleLinkedList csll = new CircleSingleLinkedList();
csll.addNode(5);
csll.showNode();
//测试小孩出圈
csll.countNode(1, 2, 5); //2 4 1 5 3
}
}
//创建一个单向的环形链表
class CircleSingleLinkedList {
//创建一个head节点
public Node head = new Node(0);
//添加节点,构建一个环形链表
public void addNode(int nums) {
//num 做一个数据校验
if (nums < 1) {
System.out.println("值不正确");
return;
}
Node cur = null; //辅助指针,帮助构建环形链表
//使用for循环来创建我们的环形链表
for (int i = 1; i <= nums; i++) {
//根据值,创建节点
Node node = new Node(i);
if (i == 1) {
head = node;
head.next = head; //构成环
cur = head;
} else {
cur.next = node;
node.next = head;
cur = node;
}
}
}
//遍历当前循环链表
public void showNode() {
if (head == null) {
System.out.println("链表空");
}
Node cur = head;
while (true) {
System.out.println(cur.value);
if (cur.next == head) {
System.out.println("遍历完,结束");
break;
}
cur = cur.next;
}
}
/*
*
* @param start 第几个小孩开始数数
* @param countNum 表示数几下
* @param nums 表示最初有多少小孩在圈中
*
*/
//根据用户的输入,计算约瑟夫环的出圈顺序
public void countNode(int start, int countNum, int nums) {
//先对数据进行校验
if (head == null || start < 1 || start > nums) {
System.out.println("参数输入有误");
}
//创建辅助指针,帮助小孩出圈
Node helper = head;
//
while (true) {
if (helper.next == head) {
break;
}
helper = helper.next;
}
//小孩报数前,先让head和helper移动k-1次
for (int i = 0; i < start - 1; i++) {
head = head.next;
helper = helper.next;
}
//当小孩报数时,让head和helper指针同时移动m-1次,然后出圈
//循环操作,直到圈中只有一个节点
while (true) {
if (helper == head) { //说明圈中只有一人
break;
}
for (int i = 0; i < countNum - 1; i++) {
head = head.next;
helper = helper.next;
}
System.out.println("出圈的小孩" + head.value);
head = head.next;
helper.next = head;
}
System.out.println("最后留下的" + head.value);
}
}
class Node {
public int value;
public Node next;
public Node(int value) {
this.value = value;
}
}