经典约瑟夫问题

目录

前言

一、Josephu

二、使用步骤

1.定义链表节点

2.创建环形列表方法

3.测试

4.输出情况


前言

约瑟夫问题为:设编号为 1,2,… n 的 n 个人围坐一圈,约定编号为 k(1<=k<=n)的人从 1 开始报数,数到m 的那个人出列,它的下一位又从 1 开始报数,数到 m 的那个人又出列,依次类推,直到所有人出列为止,由此产生一个出队编号的序列。

解决方法:依靠环形链表。


一、Josephu

情况一:假设总人数n=5,从编号为k=1开始报数,数到m=2时出列。
情况二:假设总人数n=25,从编号为k=10开始报数,数到m=5时出列。
情况三:假设总人数n=50,从编号为k=20开始报数,数到m=15时出列。

二、使用步骤

1.定义链表节点

class ListNode {
    int val;
    ListNode next;

    public ListNode(int val) {
        this.val = val;
    }
}

2.创建环形列表方法

class CircleSingleLinkedList {
    // 创建环形列表的方法
    public ListNode createCircleList(int n) {// n为总人数
        ListNode head = new ListNode(1);// 定义头结点,初始化为1
        ListNode next = head;// 初始化next的位置

        for (int i = 2; i <= n; i++) {
            ListNode temp = new ListNode(i);
            next.next = temp;
            next = next.next;// 后移一位
        }
        next.next = head;// 头尾相连
        return head;
    }

    // 出环形列表的方法
    public void outList(ListNode list, int k, int m) {
        ListNode head = list;
        ListNode prehead = head;// 定义头结点的前一个节点

        // 将prehead定位在链表最后一位
        while (true) {
            if (prehead.next == head) {
                break;
            }
            prehead = prehead.next;
        }

        // 将head定位到编号k的位置上,perhead也移动同样步数,保证prehead.next==head
        while ((k - 1) > 0) {
            head = head.next;
            prehead = prehead.next;
            k--;
        }

        System.out.print("出圈编号:");

        while (true) {
            if (head == head.next) {// 如果头结点下一个为头结点,此时只剩头结点
                break;
            }
            for (int i = 0; i < m - 1; i++) {// 移动m-1步,此时head指向的节点,是要出列的节点
                head = head.next;
                prehead = prehead.next;
            }
            // 输出编号
            System.out.print(head.val + " ");

            // 节点出列
            head = head.next;
            prehead.next = head;
        }
        // 输出最后一个编号
        System.out.print(head.val + " ");
    }
}

3.测试

public class Josepfu {
    public static void main(String[] args) {
        CircleSingleLinkedList test = new CircleSingleLinkedList();
        //情况一
        ListNode list = test.createCircleList(5);// 创建环形链表
        test.outList(list, 1, 2);// 出列
        System.out.println();
        //情况二
        ListNode list1 = test.createCircleList(25);// 创建环形链表
        test.outList(list1, 10, 5);// 出列
        System.out.println();
        //情况三
        ListNode list2 = test.createCircleList(50);// 创建环形链表
        test.outList(list2, 20, 15);// 出列
    }
}

4.输出情况


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值