约瑟夫环
约瑟夫环小游戏:把小朋友按照编号1,2,3,…,n围成一圈,指定编号为k的小朋友从1开始报数,数到m的小朋友出队。接着他的下一位小朋友再次从1报数,以此类推,直到所有人都出队,产生了一个出队编号的序列。
- 代码实现
public class Josepfu {public static void main(String[] args) {CircleLinkList list = new CircleLinkList();list.addBoy(10);list.show();list.countBoy(2, 4, 10);}/*** 使用环形链表模拟约瑟夫环*/private static class CircleLinkList {//创建头结点private Boy first;/*** 添加节点形成链表* @param nums 小朋友的人数*/void addBoys(int nums) {if (nums < 1) {System.out.println("nums的值不正确");return;}//添加辅助节点Boy current = null;for (int i=1;i<=nums;i++) {Boy boy = new Boy(i);if (i == 1) {//第一个小朋友形成自环first = boy;first.next = first;current = first;} else {current.next = boy;boy.next = first;current = current.next;}}}/*** 报数* @param startNo 从第几个小孩报数* @param countNum 表示数到几号出队* @param nums 圈中小孩的数目*/void countBoy(int startNo, int countNum, int nums){if (first == null || startNo < 1 || startNo > countNum) {System.out.println("输入参数有误,重新输入");return;}//使用辅助节点指向链表末尾Boy helper = first;while(helper.next != first) {helper = helper.next;}//小朋友报数前把first和helper移动到开始报数的小朋友的位置for (int i=0;i<startNo-1;i++) {first = first.next;helper = helper.next;}//当小朋友报数时,移动m-1次后出圈while (true) {if (first == helper) {break;}for (int j=0;j<countNum-1;j++) {first = first.next;helper = helper.next;}//first指向要出圈的节点System.out.printf("小朋友%d出圈\n", first.no);first = first.next;helper.next = first;}System.out.println("最后留在圈中的小朋友编号是:" + first.no);}/*** 显示链表中的小朋友*/void show() {if (first == null) {System.out.println("链表为空");return;}Boy current = first;while(true){System.out.printf("小朋友的编号%d\n", current.no);if(current.next == first){break;}current = current.next;}} }/*** 小朋友*/private static class Boy {int no;Boy next;Boy(int no) {this.no = no;}}
}
- 以10个小朋友,从第2号小朋友开始从1报数,数到4出圈为例,输出结果如下:
小朋友的编号8
小朋友的编号9
小朋友的编号10
小朋友5出圈
小朋友9出圈
小朋友3出圈
小朋友8出圈
小朋友4出圈
小朋友1出圈
小朋友10出圈
小朋友2出圈
小朋友7出圈
最后留在圈中的小朋友编号是:6