约瑟夫问题

约瑟夫问题

有n个人,编号为1~n,从第k(1<=k<=n)个人开始报数,从1开始报,报到m的人会出列,然后从第m+1个人开始,重复以上过程。直到所有让出列,由此产生一个出队序列

分析

构建一个单向单环形链表思路

1、先创建第一个节点,让first指向该节点,并形成环形
2、后面当我们每创建一个新当节点,就把该节点加入到已有到环形链表中

遍历环形链表思路

1、先生存一个辅助变量cur,然后指向first
2、通过while遍历,cur.next == first 结束

实现思路

输入参数n k m

1、创建一个辅助变量helper,事先指向最后一个节点

2、找到报数的目标,first和helper移动k-1次

3、当报数时候,让first和helper同时移动m-1次

4、这时候将first指向节点出圈,经过(first = first.next,Helper.next = first;),原来节点就消失了

package linkedlist;

public class Josepfu {
    public static void main(String[] args) {
        CircleSingleLinkedList circleSingleLinkedList = new CircleSingleLinkedList();
   
        circleSingleLinkedList.count(1,2,5);
    }
}
// 创建一个环形的单向链表
class CircleSingleLinkedList{

    // 创建一个first节点
    public JNode first = new JNode(-1);
    // 添加节点,构成一个环形链表
    public void add(int nums){
        if (nums < 1){
            System.out.println("添加不合理");
            return;
        }
        // 辅助变量
        JNode cur = null;
        for (int i = 1; i <= nums; i++){
            // 根据编号创建节点
            JNode jNode = new JNode(i);
            if(i == 1){
                first = jNode;
                first.next = first;
                cur = first;
            } else {
                cur.next = jNode;
                jNode.next = first;
                cur = jNode;
            }
        }
    }
    // 遍历当前环形链表
    public void list(){
        if(first == null){
            System.out.println("空");
            return;
        }
        JNode cur = first;
        while (true){
            System.out.println(cur.id);
            if (cur.next == first){
                break;
            }
            cur = cur.next;
        }
    }

    /**
     *
     * @param no 第几个节点开始
     * @param countNum 数多少下
     * @param nums 初始有多少个节点
     */
    public void count(int no,int countNum,int nums){
        // 校验
        if (first == null || no < 1 || no > nums){
            System.out.println("参数有误");
            return;
        }
        this.add(nums);
        // 创建辅助变量
        JNode helper = first;
        // 将辅助变量指向最后一个节点
        while (true){
            if (helper.next == first){
                break;
            }
            helper = helper.next;
        }
        // 找到开始的节点
        for (int j = 0; j < no-1; j++){
            first = first.next;
            helper = helper.next;
        }
        // 报数前,让first和helper同时移动 m-1 次,然后出圈
        while (true){
            if(helper == first){
                break;
            }
            for (int j = 0; j < countNum-1; j++){
                first = first.next;
                helper = helper.next;
            }
            // 出圈节点
            System.out.println(first.id);
            // 出圈
            first = first.next;
            helper.next = first;
        }
        System.out.println(helper.id);
    }
}
// 创建节点
class JNode {
    public int id;
    public JNode next;

    public JNode(int id){
        this.id = id;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值