约瑟夫问题

约瑟夫问题:N个人围成一圈,从约定编号为K的人开始报数,第M个将被杀掉,依次类推,最后剩下一个,其余人都将被杀掉。

直接上图展示,初始化状态: 假设n=6,总共有6个人,k=1,从第一个人开始报数,m=5,每次数五个。

  1 package linkedlist;
  2 
  3 public class josepfu {
  4 
  5     public static void main(String[] args) {
  6 //构建环形链表
  7         CirclesingleLinkedList circlesingleLinkedList = new CirclesingleLinkedList();
  8         circlesingleLinkedList.addBoy(5);
  9         circlesingleLinkedList.showBoy();
 10         circlesingleLinkedList.countBoy(1, 2, 5);
 11     }
 12 
 13 }
 14 
 15 //创建环形单向链表
 16 class CirclesingleLinkedList {
 17     private Boy first = new Boy(-1);
 18 
 19     public void addBoy(int nums) {
 20         if (nums < 1) {
 21             System.out.println("nums的值不正确");
 22             return;
 23         }
 24         Boy curBoy = null;
 25         for (int i = 1; i <= nums; i++) {
 26             Boy boy = new Boy(i);
 27             if (i == 1) {
 28                 first = boy;
 29                 first.setNext(first);
 30                 curBoy = first;
 31             } else {
 32                 curBoy.setNext(boy);
 33                 boy.setNext(first);
 34                 curBoy = boy;
 35             }
 36         }
 37     }
 38 
 39     // 遍历当前环形链表
 40     public void showBoy() {
 41         if (first == null) {
 42             System.out.println("没有任何小孩");
 43             return;
 44         }
 45         Boy curBoy = first;
 46         while (true) {
 47             System.out.println("小孩的编号" + curBoy.getNo());
 48             if (curBoy.getNext() == first) {
 49                 break;
 50             }
 51             curBoy = curBoy.getNext();
 52 
 53         }
 54     }
 55 
 56     // 根据用户的输入,计算小孩出圈的顺序
 57     /**
 58      * 
 59      * @param startNo表示从第几个小孩开始数数
 60      * @param counntNum表示数几下
 61      * @param nums表示最初有多少小孩在圈中
 62      */
 63     public void countBoy(int startNo, int countNum, int nums) {
 64         // 先对数据校验
 65         if (first == null || startNo < 1 || startNo > nums) {
 66             System.out.println("参数有误");
 67         }
 68         Boy helper = first;
 69         // helper指向环形链表的最后节点
 70         while (true) {
 71             if (helper.getNext() == first) {
 72                 break;
 73             }
 74             helper = helper.getNext();
 75         }
 76         // 小孩报数前,先让first和helper移动k-1次
 77         for (int j = 0; j < startNo - 1; j++) {
 78             first = first.getNext();
 79             helper = helper.getNext();
 80         }
 81         // 让first和helper指针同时移动m-1次,然后出圈
 82         while (true) {
 83             if (helper == first) {// 圈中只有一个
 84                 break;
 85 
 86             }
 87             // 让first和helper指针同时移动countNum-1
 88             for (int j = 0; j < countNum - 1; j++) {
 89                 first = first.getNext();
 90                 helper = helper.getNext();
 91             }
 92             // 这时first指向的节点,就是要出圈的小孩节点
 93             System.out.println("小孩" + first.getNo() + "出圈");
 94             first = first.getNext();
 95             helper.setNext(first);
 96         }
 97         System.out.println("留在圈中的小孩编号" + first.getNo());
 98     }
 99 
100 }
101 
102 class Boy {
103     private int no;
104     private Boy next;
105 
106     public Boy(int no) {
107         super();
108         this.no = no;
109     }
110 
111     public int getNo() {
112         return no;
113     }
114 
115     public void setNo(int no) {
116         this.no = no;
117     }
118 
119     public Boy getNext() {
120         return next;
121     }
122 
123     public void setNext(Boy next) {
124         this.next = next;
125     };
126 
127 }
原文地址:https://www.cnblogs.com/-xuewuzhijing-/p/12887847.html