• 约瑟夫环问题——《算法》1.1.37的解法


    话不多说,先给出题的图

     这个题的意思就是给一个人数N,比如7,从0开始标号,0,1,2,3,4,5,6。这样最后一个就是6。然后再报一个数M,比如2,

    这样第一次从0开始,数2,就是标号为1的在第一轮出局。这样剩下0,2,3,4,5,6,

    这次是从2,开始数,这样出局的是3,剩下0,2,4,5,6。

    然后从4开始数,出局的是5,剩下0,2,4,6。

    然后从6开始数,出局的是0,剩下2,4,6。

    这次从2开始数,这样出局的是4,剩下2,6。

    最后从6开始数,2出局。剩下6。

    6。

    一、问题思路

    题目是要编写一个Queue的用例。一开始想到如果M比较大,剩下的数比较少的时候,怎么办?可以考虑用M对剩下的数取模的方法。后来想到用环形的单链表其实还比较容易实现。

     像图示那样,设计一个单向环链表,然后设置一个where指针,一开始指向所加的最后一个元素6。然后要删除的时候,比如M=2,让where指针走M-1次next就可以指向“1”,然后用delete方法删除1就可以了。然后再次走的话,再重复就可以了。

    二、解决方案

    1、设计node类

    链表上的每个元素包含1个int类型数值,还要包含node,指向next。

    1. class Node{
    2. int num;
    3. Node next;
    4. Node(){
    5. this.num = 100;
    6. this.next = null;
    7. }
    8. Node(int element) {
    9. this.num = element;
    10. this.next = null;
    11. }
    12. }

    2、创建josephus环

    1. public void create(){
    2. this.josephus = new Node();
    3. this.where = josephus;
    4. this.nodenum = 0;
    5. }

    一开始where指针指向头节点josephus.

    3、如何加元素

    增加一个元素的话,让新增的元素放在where后面,所以where.next = newNode ,然后再让where向前移动一格,where= where.next。新节点指向第一个节点。newNode.next = josephus.next.然后整个环的节点数+1。

    1. public void add(int element){
    2. Node newNode = new Node(element);
    3. where.next= newNode;
    4. this.where = newNode;
    5. newNode.next = this.josephus.next;
    6. this.nodenum++;
    7. }

    4、如何删除元素。因为约瑟夫环要求删除某个元素,有一个参数M。

    根据我们的分析,对于参数M,就是让where指针向前走M-1步,然后删除where.next节点,就是让where.next = where.next.next,记录被删除元素的节点num值。

    1. public int minus(int M){
    2. int deleted;
    3. for(int i = 1 ; i < M ; i++)
    4. where = where.next;
    5. deleted = where.next.num;
    6. where.next = where.next.next;
    7. this.nodenum--;
    8. return deleted;
    9. }

    当然这里最好有个是否为空的判断。

    5、最后给出测试用例:

    1. public static void main(String[] args) {
    2. Josephus josephus = new Josephus();
    3. josephus.create();
    4. int i;
    5. for( i = 0 ; i < 10 ; i ++ )
    6. josephus.add(i);
    7. System.out.println(josephus.where.num);
    8. for(i = 1; i < 10;i++) {
    9. int minus = josephus.minus(17);
    10. System.out.print(minus+" ");
    11. }
    12. }
    1. 9
    2. 6 4 5 9 7 0 1 3 8
    3. Process finished with exit code 0

    6、最后给出全部类及测试的代码

    1. class Node{
    2. int num;
    3. Node next;
    4. Node(){
    5. this.num = 100;
    6. this.next = null;
    7. }
    8. Node(int element) {
    9. this.num = element;
    10. this.next = null;
    11. }
    12. }
    13. public class Josephus {
    14. int nodenum;
    15. Node josephus;
    16. Node where;
    17. public void create(){
    18. this.josephus = new Node();
    19. this.where = josephus;
    20. this.nodenum = 0;
    21. }
    22. public int size(){return this.nodenum;}
    23. public void add(int element){
    24. Node newNode = new Node(element);
    25. where.next= newNode;
    26. this.where = newNode;
    27. newNode.next = this.josephus.next;
    28. this.nodenum++;
    29. }
    30. public int minus(int M){
    31. int deleted;
    32. for(int i = 1 ; i < M ; i++)
    33. where = where.next;
    34. deleted = where.next.num;
    35. where.next = where.next.next;
    36. this.nodenum--;
    37. return deleted;
    38. }
    39. public static void main(String[] args) {
    40. Josephus josephus = new Josephus();
    41. josephus.create();
    42. int i;
    43. for( i = 0 ; i < 10 ; i ++ )
    44. josephus.add(i);
    45. System.out.println(josephus.where.num);
    46. for(i = 1; i < 10;i++) {
    47. int minus = josephus.minus(17);
    48. System.out.print(minus+" ");
    49. }
    50. }
    51. }

  • 相关阅读:
    使用Nacos作为配置中心
    Spring面试题14:Spring中什么是Spring Beans? 包含哪些?Spring容器提供几种方式配置元数据?Spring中怎样定义类的作用域?
    非谓语动词
    处理查询结果集
    基于ChatGPT函数调用来实现C#本地函数逻辑链式调用助力大模型落地
    vue3对数据进行类型验证
    Ubuntu20.04安装gRPC-go
    fetch-axios简述和简单用法
    (三)softmax分类--九五小庞
    数据结构——顺序表和链表
  • 原文地址:https://blog.csdn.net/m0_47161778/article/details/125554588