约瑟夫环-java

一、问题描述:

设有 N 个人围坐一圈并按顺时针方向从 1 N 编号,从第 S 个人开始进行 1 M 报数,报数到第 M 的人,此人出圈,再从他的下一个人重新开始从 1 M 报数,如此进行下去,每次报数到M 的人就出圈,直到所有人都出圈为止。给出这 N 个人的出圈顺序。
举一个简单的例子来更好的理解题目,假设有10( N)个人,从第3( S)个人开始进行1到2( M)报数,报数到第二个人出圈, 再从他的下一个人重新开始从 1 M 报数,直到所有人出圈,给出这10个人出圈顺序。

 

图中红色数字代表座位顺序,绿色数字为第一次循环出圈的人以及顺序,紫色数字为第二次出圈的人以及顺序,蓝色、黄色分别为第三次、第四次。我们的目的是求出 红色数字的出圈顺序
出圈顺序为: 4 6 8 10 2 5 9 3 1 7
二、两种解题思路(均为数组法)
第一种:
public class Joseph {
    public static void main(String[] args) {
        final int N = 10,S = 3,M=2; //定义基本数据
        int i = S-1,j,k=10,g=1;    
        int[] a = new int[10];  //定义容量为十人的数组


        for(int h = 1 ;h<=10;h++){
            a[h-1] = h;} //将十个人对应的序号输入数组中


            System.out.print("\n出圈的顺序为:");
            do
            {
             i = i + (M-1); //直接定位到出圈人的下标


             while(i >= k){     //使i能循环进行
                 i = i-k;
             }

                System.out.println(" "+a[i]);  //打印出圈人的序号

             for(j = i;j<k-1;j++){
                 a[j] = a[j+1];}  //a[i]出圈后,a[i]后的人要向前移一位

             k--;    //剩下总人数减一
             g++;   //出圈人数加1

            }while(g<=10); //循环在所有人出圈后停止

    }
}

定义一个while循环,循环在每一次执行时会排一人出圈,并且其余人构成下一次循环体(例如第一次循环后其余九人围成圆圈),在所有人出圈后,循环停止。并且每次有人出圈后都会即时打印出圈人序号。

第二种:

public class Joseph2 {
    public static void main(String[] args) {
        final int N = 10,S = 3,M = 2;
        int []p = new int[10];     //定义数组用来标记出圈人
        int []q = new int[10];     //定义数组用来接收出圈人的序号
        int k,n = 0;      
        k = 1;                   //从1开始数数
        for(int i = 1;i<= 10;i++){
            //第一个for循环每循环一次增加一个出圈人
            //p[k]用来标记出圈人,没循环一次p[k]标记一次
            for(int j = 1;j<=2;j++){   
                if(k == N-1){      
                    k = 0;          //当数到最后一人时,回到第一个人开始数
                }
                else{
                    k++;         //数数
                }
                if(p[k]==1){
                    j--;           //如果数到了出圈人,此次循环作废,循环次数加一
                }
            }
            p[k] = 1;          //标记出圈人
            q[n++]=k+1;         //接收出圈人序号
        }
        System.out.println("出圈顺序为:");
        for (int i = 0; i < N; i++) {
            System.out.print(q[i]+"    ");          //遍历序号
        }
    }
}

数数法,两个for循环会从1开始数数,并且数到出圈人会将其标记,直到所有人都被标记之后,循环结束。

“约瑟夫环”还有更多解法,笔者能力有限,本篇也仅供参考。

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值