package com.datastructures.linkedlist;
public class JosephQuestion {
public static void main(String[] args) {
CircleSingleLinkedList circleSingleLinkedList = new CircleSingleLinkedList();
circleSingleLinkedList.addBoy(5);
circleSingleLinkedList.showList();
System.out.println("开始出圈");
circleSingleLinkedList.countBoy(1, 2, 5);
}
}
class CircleSingleLinkedList {
private Boy first;
public void addBoy(int nums) {
if (nums <= 0) {
System.out.println("nums的值不正确");
return;
}
Boy cur = first;
for (int i = 1; i <= nums; i++) {
if (i == 1) {
first = new Boy(i);
cur = first;
} else {
cur.setNext(new Boy(i));
cur = cur.getNext();
}
}
cur.setNext(first);
}
public void showList() {
if (first == null) {
System.out.println("当前链表为空");
return;
}
Boy cur = first;
while (true) {
System.out.println(cur.getNo());
if (cur.getNext() == first) {
break;
}
cur = cur.getNext();
}
}
// 根据用户的输入,计算出小孩出圈的顺序
/**
*
* @param startNo 从第几个小孩开始
* @param countNum 表示数几下
* @param nums 小孩的数量
*/
public void countBoy(int startNo, int countNum, int nums) {
// 数据的校验
if (startNo > nums || startNo < 1 || first == null) {
System.out.println("数据有误");
}
// 初始化辅助指针和起始位置的指针
Boy start; // 起始位置
Boy helper = first; // 起始位置的前一个位置
for (int i = 1; i <= nums; i++) {
// 通过取模的方式获取到指定位置的前一个位置,当条件成立的时候就helper的位置正确
// (i + 1)%nums:i+1实际上是表示start指针应该存在的位置,也就是helper的下一个位置,通过取模的方式可以避免临界溢出的问题,
// 比如nums为5,那么5+1实际上取模后为1,如果指定的起始位置为1,那么i+1是start指针的位置,(i+1)%nums是helper指针的位置
// startNo%nums同样也是为了取得正确的临界值,如果起始位置为5,那么5%5=0,只有i=4的时候,条件才成立,才可以使得helper指针
// 在4的位置
if ((i + 1)%nums == startNo%nums) {
break;
}
// 随着i的递增,位置也应该改变
helper = helper.getNext();
}
// 将start指针置于正确的起始位置
start = helper.getNext();
// 设置移动步数,由于出圈一个后,就会初始指针会进行移动,因此需要-1,如果countNum为2,
// 那么helperCountNum就是1,只需要移动1步后到达指定位置
int helperCountNum = countNum - 1;
// 如果两个指针指向同一个位置,表示只剩下一个小孩未出圈
while (start != helper) {
// 步数执行完毕
if (helperCountNum == 0) {
// 输出当前start指针的值
System.out.println(start.getNo());
// helper指向start的next
helper.setNext(start.getNext());
// start更新,表示指向的小孩出圈
start = helper.getNext();
// 初始化helperCoutNum的值
helperCountNum = countNum - 1;
} else { // 继续执行步数
// start后移
start = start.getNext();
// helper后移
helper = helper.getNext();
// 步数递减
helperCountNum--;
}
}
// 将最后的小孩出圈
System.out.println(start.getNo());
// 头指针指向null,全部出圈完毕
first = null;
}
}
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;
}
}
约瑟夫环问题-小孩出圈-Java实现
最新推荐文章于 2024-08-04 17:16:44 发布