.NET转JAVA之路005

约瑟夫环

约瑟夫环(约瑟夫问题)是一个数学的应用问题:已知n个人(以编号1,2,3…n分别表示)围坐在一张圆桌周围。从编号为k的人开始报数,数到m的那个人出列;他的下一个人又从1开始报数,数到m的那个人又出列;依此规律重复下去,直到圆桌周围的人全部出列。通常解决这类问题时我们把编号从0~n-1,最后[1] 结果+1即为原问题的解。
这里我们简化模型,500个人小朋友围城一个圈,数三退出,求出最后一个人的下标是多少

思路一:构建一个500个bool数组,初始时全部为true,数到三时,赋值为false,
只要求出最后一个数组为true的下标数字,即为所求数字。


         boolean[] arr=new boolean[500];//创建bool数组
         for(int i=0;i<arr.length;i++){
            arr[i]=true; //初始时都为true;
         }

         int leftcount=arr.length;//记录当前圈内还有多少人

         int countNum=0;//1,2,3,1,2,3的记录值

         int index=0; //当前的索引值,超出500返回0;

         while(leftcount>1){//只要圈内人还多于1个人,继续执行
            if(arr[index]==true){
                countNum++;
                if(countNum==3)
                {
                    countNum=0;
                    arr[index]=false; //出列
                    leftcount--; //圈内人数减1
                }
            }

            index++; //索引自增长
            if(index==arr.length){
                index=0; //超出索引值,返回到头部
            }
         }

         for(int i=0;i<arr.length;i++)
        {
            if(arr[i]==true)
            {
                System.out.println(i); //获得唯一的一个没有出列的数字
            }
         }

思路二:小朋友手拉手(双向链表)
先上图:
这里写图片描述

//小朋友类
class Kid
{
    int id;
    Kid left;
    Kid right;
}

class KidCircle
{
    int count=0;
    Kid first,last;
    KidCircle(int n){
        for(int i=0;i<n;i++){
            add();
        }
    }

    void add(){
        Kid k=new Kid();
        k.id=count;
        if(count<=0)
        {
            first=k;
            last=k;
            k.left=k;
            k.right=k;
        }else{
            last.right=k;
            k.left=last;
            k.right=first;
            first.left=k;
            last=k;
        }
        count++;
    }

    void delete(Kid k)
    {
        if(count<=0)
        {
            return ;
        }else if(count==1){
            first=last=null;
        }else{
            k.left.right=k.right;
            k.right.left=k.left;

            if(k==first){
            first=k.right;
            } else if(k==last){
            last=k.left;
            }
        }
        count--;
    }
}

主程序

public static void main(String[] args) 
 {
        KidCircle kc=new KidCircle(500);
        int countNum=0; 
        Kid k=kc.first; 
        while(kc.count>1)
        {
            countNum++;
            if(countNum==3)
            {
                countNum=0;
                kc.delete(k);
            } 
            k=k.right;
        } 
        System.out.println(kc.first.id);

    }
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值