Josephus环的四种解法(约瑟夫环)

约瑟夫环

约瑟夫环(约瑟夫问题)是一个数学的应用问题:已知n个人(以编号1,2,3…n分别表示)围坐在一张圆桌周围。从编号为k的人开始报数,数到m的那个人出列;他的下一个人又从1开始报数,数到m的那个人又出列;依此规律重复下去,直到圆桌周围的人全部出列。通常解决这类问题时我们把编号从0~n-1,最后结果+1即为原问题的解
引用别人的一个图:直观说明问题

分析:

第一步:从1开始报数为3的时候就删除3号结点
第二步:从4号结点开始报数,当为3的时候删除6号结点;
第三步:从7号结点开始报数,当为3的时候删除1号结点;
第四步:从2号结点开始报数,当为3的时候删除5号结点;
第五步:从7号结点开始报数,当为3的时候删除2号结点;
第六步:从4号元素开始报数,当为3的时候删除8号结点;
第七步:又从4号开始报数,当为3的时候删除4号结点,此时链表中只有一个7号结点,所以最后的结点就是7号结点;

1.模拟解法

public class 模拟 {

    public static void main(String[] args) {
        Scanner in=new Scanner(System.in);

        //总人数
        int n=in.nextInt();
        // 数到m的那个人出列
        int m=in.nextInt();
        // 初始化为0 都没有出去
        int [] arr=new int[n];

        //剩下的人数
        int peopleLeft=n;
        //初始化下标
        int index=0;
        // 下标计算器
        int count=0;
        // >0 出循环为负
        while (peopleLeft>1){
           if(arr[index]==0){
               // count为计步器 不是下标指向
                count++;
               if(count==m){
                   arr[index]=1;
                   count=0;
                   peopleLeft--;
               }
           }
           index++;
           if(index==arr.length){
               index=0;
           }

        }
        for (int i = 0; i < arr.length; i++) {
            if(arr[i]==0){
                System.out.println(i+1);
            }
        }
    }
}

2.递归解法

  /**
     * 递归式:
     * f(1)=0; 第一个位置永远为0
     * f(i)=f(i)+m%n;
     */
    public static int yuesefu(int n,int m){
        if(n==1){
            return 0;
        }else {
            return (yuesefu(n-1,m) + m) % n;
        }
    }

    public static void main(String[] args) {
        System.out.println(yuesefu(41,3)+1);
        vailCode(41,3);
    }

    //逆推验证代码

    public static void vailCode(int a,int b){
        System.out.print(b);
        int reslut;
        for (int i = a; i >=2 ; i--) {
             reslut=2;
            for (int j = i; j <=a ; j++) {
                reslut=(reslut+b)%j;
            }
            System.out.printf("->%d",reslut+1);
        }
    }

3.循环链表解法

public class  CircularLinkedList {

    public static void main(String[] args) {
        /**
         * 节点类
         */
        class Node{
            private int data=1;
            private Node next;
            Node(){
                next=null;
            }
        }

        Node head,temp;
        head=new Node();
        head.data=1;

        int a=41;
        int b=3;
        // 临时节点
        temp=head;
        for (int i = 0; i < a; i++) {
            Node new_node=new Node();
            new_node.data=i+1;
            temp.next=new_node;
            temp=new_node;
        }
        temp.next=head.next;

        while (head.next!=head){
           for (int i = 0; i < b-1; i++) {
                head=head.next;
            }
            System.out.print("->"+(head.data+1));
            head.next=head.next.next;
        }
        System.out.println(head.data);

    }
}

4.Collection解法

 public static void main(String[] args) {
        int a=41;
        int b=3;
        LinkedList<Integer> list = new LinkedList<>();
        for (int i = 0; i < a; i++) {
            list.add(i+1);
        }
        while (list.size()>1){
            for (int i = 0; i < b-1; i++) {
                list.add(list.remove());
            }
            System.out.print("->"+list.getFirst());
            list.remove();//remve head
        }
        System.out.println(list.getFirst());
    }

原文地址:https://www.cnblogs.com/dgwblog/p/10086189.html

时间: 2024-10-08 01:28:20

Josephus环的四种解法(约瑟夫环)的相关文章

*HDU 1394 经典逆序数的四种解法

1.暴力 [代码]: 1 /*HDU1394暴力写法*/ 2 #include <iostream> 3 #include <string.h> 4 #include <stdio.h> 5 6 using namespace std; 7 8 int A[50005]; 9 int Low[50005],Up[50005]; 10 int main(){ 11 int n; 12 while(~scanf("%d",&n)){ 13 int

整数拆分问题的四种解法【转载】

http://blog.csdn.net/u011889952/article/details/44813593 整数拆分问题的四种解法 原创 2015年04月01日 21:17:09 标签: 算法 / 母函数定理 / 五边形数定理 / acm / 动态规划 整数划分问题是算法中的一个经典命题之一 所谓整数划分,是指把一个正整数n写成如下形式: n=m1+m2+m3+....+mi;(其中mi为正整数,并且1<=mi<=n),则{m1,m2,m3,....,mi}为n的一个划分. 如果{m1,

【转载转载转载!】整数拆分问题的四种解法--尼奥普兰

整数拆分问题的四种解法 原创 2015年04月01日 21:17:09 标签: 算法 / 母函数定理 / 五边形数定理 / acm / 动态规划 整数划分问题是算法中的一个经典命题之一 所谓整数划分,是指把一个正整数n写成如下形式: n=m1+m2+m3+....+mi;(其中mi为正整数,并且1<=mi<=n),则{m1,m2,m3,....,mi}为n的一个划分. 如果{m1,m2,m3,....,mi}中的最大值不超过m,即max{m1,m2,m3,....,mi} <= m,则称

LeetCode算法题-Valid Perfect Square(Java实现-四种解法)

这是悦乐书的第209次更新,第221篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第77题(顺位题号是367).给定正整数num,写一个函数,如果num是一个完美的正方形,则返回True,否则返回False.例如: 输入:16 输出:true 输入:14 输出:false 注意:不要使用任何内置库函数,例如sqrt. 本次解题使用的开发工具是eclipse,jdk使用的版本是1.8,环境是win7 64位系统,使用Java语言编写和测试. 02 第一种解法 暴力解法

LeetCode算法题-Minimum Distance Between BST Nodes(Java实现-四种解法)

这是悦乐书的第314次更新,第335篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第183题(顺位题号是783).给定具有根节点值的二叉搜索树(BST),返回树中任何两个不同节点的值之间的最小差值.示例: 给定的树[4,2,6,1,3,null,null]由下图表示: 4 / 2 6 / \ 1 3 输出:1 说明:请注意,root是TreeNode对象,而不是数组.该树中的任意节点最小差值为1,它发生在节点1和节点2之间,也发生在节点3和节点2之间. 注意: BS

小朋友学数据结构(1):约瑟夫环的链表解法、数组解法和数学公式解法

约瑟夫环的链表解法.数组解法和数学公式解法 约瑟夫环(Josephus)问题是由古罗马的史学家约瑟夫(Josephus)提出的,他参加并记录了公元66-70年犹太人反抗罗马的起义.约瑟夫作为一个将军,设法守住了裘达伯特城达47天之久,在城市沦陷之后,他和40名死硬的将士在附近的一个洞穴中避难.在那里,这些叛乱者表决说"要投降毋宁死".于是,约瑟夫建议每个人轮流杀死他旁边的人,而这个顺序是由抽签决定的.约瑟夫有预谋地抓到了最后一签,并且,作为洞穴中的两个幸存者之一,他说服了他原先的牺牲品

约瑟夫环以及其变种集合

最近在CF上补题,补到了一道关于约瑟夫环的题目(听都没听过,原谅我太菜) 就去好好学了一下,不过一般的题目应该是不会让你模拟过的,所以这次就做了一个约瑟夫环公式法变形的集合. 关于约瑟夫环的基础讲解,我个人认为最好的就是这篇了. 首先是最原始的约瑟夫环的题目: https://vjudge.net/problem/51Nod-1073(小数据规模) #include <bits/stdc++.h> using namespace std; int main() { ios::sync_with

LeetCode算法题-Find the Difference(Java实现-五种解法)

这是悦乐书的第214次更新,第227篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第82题(顺位题号是389).给定两个字符串s和t,它们只包含小写字母.字符串t由随机混洗字符串s生成,然后在随机位置再添加一个字母.找到t中添加的字母.例如: 输入:s ="abcd", t ="abcde" 输出:'e' 说明:'e'是添加的字母. 本次解题使用的开发工具是eclipse,jdk使用的版本是1.8,环境是win7 64位系统,使用Jav

约瑟夫环问题的两种实现[链表+数组]

约瑟夫环是一个数学的应用问题:已知n个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围.从编号为k的人开始报数,数到m的那个人出列:他的下一个人又从1开始报数,数到m的那个人又出列:依此规律重复下去,直到圆桌周围的人全部出列. 以下是使用循环链表和数组的两种实现: 1 #include<iostream> 2 using namespace std; 3 4 struct Node 5 { 6 int data; 7 Node *next; 8 }; 9 void CreateLink