约瑟夫环实现

约瑟夫环

约瑟夫环小游戏:把小朋友按照编号1,2,3,...,n围成一圈,指定编号为k的小朋友从1开始报数,数到m的小朋友出队。接着他的下一位小朋友再次从1报数,以此类推,直到所有人都出队,产生了一个出队编号的序列。

  1. 代码实现
java 复制代码
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;
        }
    }
}
  1. 以10个小朋友,从第2号小朋友开始从1报数,数到4出圈为例,输出结果如下:

小朋友的编号8

小朋友的编号9

小朋友的编号10

小朋友5出圈

小朋友9出圈

小朋友3出圈

小朋友8出圈

小朋友4出圈

小朋友1出圈

小朋友10出圈

小朋友2出圈

小朋友7出圈

最后留在圈中的小朋友编号是:6

相关推荐
uhakadotcom33 分钟前
使用 Python 与 BigQuery 进行交互:基础知识与实践
算法·面试
uhakadotcom33 分钟前
使用 Hadoop MapReduce 和 Bigtable 进行单词统计
算法·面试·github
XYY3691 小时前
前缀和 一维差分和二维差分 差分&差分矩阵
数据结构·c++·算法·前缀和·差分
longlong int1 小时前
【每日算法】Day 16-1:跳表(Skip List)——Redis有序集合的核心实现原理(C++手写实现)
数据库·c++·redis·算法·缓存
24白菜头1 小时前
C和C++(list)的链表初步
c语言·数据结构·c++·笔记·算法·链表
刺客-Andy2 小时前
前端加密方式 AES对称加密 RSA非对称加密 以及 MD5哈希算法详解
前端·javascript·算法·哈希算法
记得早睡~2 小时前
leetcode122-买卖股票的最佳时机II
javascript·数据结构·算法·leetcode
黄油烤菠萝2 小时前
蓝桥杯-卡java排序
c++·算法·蓝桥杯
不要天天开心2 小时前
Scala集合
图像处理·算法·机器学习·scala
uhakadotcom2 小时前
Google Cloud Dataproc:简化大数据处理的强大工具
后端·算法·面试