约瑟夫问题概述:
Josephu问题为:设编号为 1,2,… n的 n个人围坐一圈,约定编号为 k(1<=k<=n)的人从 1开始报数,数到m的那个人出列,它的下一位又从 1开始报数,数到 m的那个人又出列,依次类推,直到所有人出列为止,由此产生一个出队编号的序列。
解决方法:
用单向环形链表解决,根据尚硅谷的网课实现的,记录一下,方便回顾。
package com.zhen.linkedlist;
//解决约瑟夫问题
public class Jusepfu {
public static void main(String[] args) {
CircleSingleLinkedList list=new CircleSingleLinkedList();
list.add(5);
list.showList();
list.countBoy(1,2,5);
}
}
class CircleSingleLinkedList{
private Boy first=null;
public void add(int nums){
//对nums数字做判断
if(nums<=0){
System.out.println("参数不合法");
return;
}
Boy temp=null;
for (int i = 1; i <=nums ; i++) {
Boy boy1 = new Boy(i);
if (i==1){
first = boy1;
first.setNext(first);
temp=first;
}
temp.setNext(boy1);
boy1.setNext(first);
temp=boy1;
}
}
public void showList(){
if (first==null){
System.out.println("环形链表还没有创建");
return;
}
Boy boy=first;
while (true){
System.out.println(boy.toString());
if (boy.getNext()==first) break;//说明已经遍历完毕
boy=boy.getNext();
}
}
/*
startNo:从第几个孩子开始数
countNum:数几个数
nums:孩子的个数
*/
public void countBoy(int startNo,int countNum,int nums){
if (first==null||startNo>nums||countNum<1){
System.out.println("输入的参数不合法");
return;
}
//创建一个辅助指针,帮助完成小孩出圈
Boy helper=first;
while (true){
if (helper.getNext()==first){
break; //让helper指向链表的最后一个结点
}
helper=helper.getNext();
}
//小孩报数前,让first指向报数的小孩,helper指向first的后面,也就是移动startNO-1次
for (int i = 0; i < startNo-1; i++) {
helper=helper.getNext();
first=first.getNext();
}
//让小孩报数,一个个出圈,直到就剩下一个小孩,也就是helper==first
while (true){
if (helper==first){
break;
}
for (int i = 0; i < countNum-1; i++) {
helper=helper.getNext();
first=first.getNext();
}
System.out.println(first.getNo()+" ");
first=first.getNext();
helper.setNext(first);
}
System.out.println(helper.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;
}
@Override
public String toString() {
return "Boy{" +
"no=" + no +
'}';
}
}