约瑟夫环
特点
描述
N个人围成一圈,从第一个开始报数,第M个将被杀掉,最后剩下一个,其余人都将被杀掉。例如N=6,M=5,被杀掉的顺序是:5,4,6,2,3。
分析:
(1)由于对于每个人只有死和活两种状态,因此可以用布尔型数组标记每个人的状态,可用true表示死,false表示活。
(2)开始时每个人都是活的,所以数组初值全部赋为false。
(3)模拟杀人过程,直到所有人都被杀死为止。
代码实现
/*** @author laoduan* @create 2020-04-09-22:27*/public class josepfu {public static void main(String[] args) {CircleSingleLinkedList circleSingleLinkedList = new CircleSingleLinkedList();circleSingleLinkedList.addBoy(25);// circleSingleLinkedList.showboy();circleSingleLinkedList.josepfu(1, 2, 25);}}//创建一个环形的单向列表class CircleSingleLinkedList {private Boy first = null;//添加小孩节点,组成环形链表public void addBoy(int nums) {if (nums < 1) {System.out.println("nums的值不正确");return;}Boy curBoy = null;//用for来创建环形链表for (int i = 1; i <= nums; i++) {Boy boy = new Boy(i);//如果是第一个小孩if (i == 1) {first = boy;first.setNext(first);curBoy = first;//让curBoy指向第一个小孩} else {curBoy.setNext(boy);boy.setNext(first);curBoy = boy;}}}//遍历当前环形链表public void showboy(){if(first==null){System.out.println("没有小孩");return;}//first不能动,要用辅助指针Boy curBoy =first;while (true){System.out.printf("当前小孩的编号%d\n",curBoy.getNo());if(curBoy.getNext()==first){//说明循环完毕break;}else {curBoy=curBoy.getNext();}}}//约瑟夫public void josepfu(int startNo,int n,int nums){if (first==null||startNo<1||startNo>nums){System.out.println("参数有误");return;}Boy helper = first;while (true){if(helper.getNext()==first){break;}helper=helper.getNext();}for(int j=0;j<startNo-1;j++){first=first.getNext();helper=helper.getNext();}while (true){if(helper==first){break;}for (int x=0;x<n-1;x++){first=first.getNext();helper=helper.getNext();}System.out.printf("出圈的小孩编号为%d\n",first.getNo());first=first.getNext();helper.setNext(first);}System.out.printf("最后剩下的小孩是%d\n",first.getNo());}}//创建一个boy类,表示一个结点class Boy {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;}public Boy (int no ){this.no = no;}private int no;private Boy next;}
