Python 每日一记235>>>Java约瑟夫问题

一、什么是约瑟夫问题

百度百科如是说:据说著名犹太历史学家 Josephus有过以下的故事:在罗马人占领乔塔帕特后,39 个犹太人与Josephus及他的朋友躲到一个洞中,39个犹太人决定宁愿死也不要被敌人抓到,于是决定了一个自杀方式,41个人排成一个圆圈,由第1个人开始报数,每报数到第3人该人就必须自杀,然后再由下一个重新报数,直到所有人都自杀身亡为止。然而Josephus 和他的朋友并不想遵从。首先从一个人开始,越过k-2个人(因为第一个人已经被越过),并杀掉第k个人。接着,再越过k-1个人,并杀掉第k个人。这个过程沿着圆圈一直进行,直到最终只剩下一个人留下,这个人就可以继续活着。问题是,给定了和,一开始要站在什么地方才能避免被处决?Josephus要他的朋友先假装遵从,他将朋友与自己安排在第16个与第31个位置,于是逃过了这场死亡游戏。

二、约瑟夫问题程序设计思路

首先,我们想到的是环的问题,而单项环形链表则正好可以作为这个问题的模型载体,从节点1开始,依次循环每个节点,当节点为3时,将这个节点删除,怎么删除呢,只需要将上一个节点指向这个节点的下一个节点即可,然后再从下一个节点开始从1数,到3又执行删除操作,直到最后只剩下一个节点,就是最后能存活下来的人,我们每次删除节点,就打印一下被删除的节点元素,这样就知道依次被删除的节点了,于是问题转化如下图:
在这里插入图片描述

二、Java代码实现

package mypackage;

//测试
public class MyJava {

    //节点类
    private static class Node<T> {
        T data;
        Node next;

        //构造方法
        public Node(T data, Node next) {
            this.data = data;
            this.next = next;
        }
    }

    public static void main(String[] args) {
//        创建一个含有41个节点的环形链表
//        记录首节点和某个节点的前一个节点
        Node<Integer> first=null;
        Node<Integer> pre=null;
//        特别要理解怎么创建的循环链表
        for (int i=1;i<=41;i++) {
//            第一次循环,创建第一个节点
//            此时pre=first
            if (i==1){
                first=new Node<>(i,null);
                pre=first;
            }

//            如果不是第一个节点
//            先创建一个新节点,让上一个节点指向新节点,且让这个新节点成为pre,用于下一次循环的上一个节点
//            并且需要判断,如果此次循环的i=41,则让这个节点指向first,形成环
            else {
                Node newnode=new Node(i,null);
                pre.next=newnode;
                pre=newnode;

//            如果是最后一个节点
                if(i==41) {
                    pre.next=first;
//                    也可以是newnode.next=first;
                }
            }
        }
//        开始约瑟夫问题的操作
//        先定义一个计数器,用于后续循环记录报数
        int count=0;
//        当前节点和前一个节点
        Node curnode=first;
        Node<Integer> beforenode=null;
        System.out.println("依次应该自杀的节点如下:");
//        开始循环,循环结束的标志是自循环,即只剩下一个节点
        while (curnode!=curnode.next){
//            计数,相当于第几个报数的,注意是first是第一个报数的
            count++;
//            如果不是第三个报数的,让beforenode=curnode,然后再让curnode后移一个节点
            if (count!=3){
                beforenode=curnode;
                curnode=curnode.next;
            }
//            如果是第三个报数的,让beforenode的指向curnode的下一个节点
//            并且打印出curnode,归零count从新计数,且让curnode后移一个节点
            else {
                beforenode.next= curnode.next;
                System.out.print(curnode.data+",");
                count=0;
                curnode=curnode.next;
            }
        }
//        最后一个元素
        System.out.print(curnode.data);

    }
}

结果:
在这里插入图片描述

发布了235 篇原创文章 · 获赞 24 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/weixin_44663675/article/details/105481351
今日推荐