约瑟夫环问题

【题目】

n个人(编号0~(n-1)),从0开始报数,报到(m-1)的退出,剩下的人 继续从0开始报数。求胜利者的编号。

【代码】

    //约瑟夫环问题
    public static int Joseph1(int n,int m){
        if(n<=0||m<1){
            return -1;
        }
        List<Integer> list=new ArrayList<Integer>();
        for(int i=0;i<n;i++){
            list.add(i);
        }
        int index=(m-1)%n;//第一个报m-1的人
        while(list.size()>1){
            list.remove(index);//除去报m-1的人
            index=(m-1+index)%list.size();//后面报m-1的人    
        }
        return list.get(0); //最后只剩下一个,即胜利者
    }

    public static int Joseph2(int n,int m){
        if(n<=0||m<1){
            return -1;
        }
        int[] arr=new int[n];
        int count=n;
        int index=-1;
        int step=0;
        while(count>1){
            index++;
            if(index==n){//相当于首尾相连
                index=0;
            }
            if(arr[index]==-1){
                continue;
            }
            step++;
            //报数为m-1的人 出局,重新报数
            if(step==m){
                count--;
                arr[index]=-1;
                step=0;
            }
        }

        for(int i=0;i<arr.length;i++){
            if(arr[i]!=-1){
                //所有出局的人对应数组元素值都为赋值为-1
                index=i;
                break;
            }
        }
        return index;       
    }

//同上思路,但代码更简洁
链接:https://www.nowcoder.com/questionTerminal/f78a359491e64a50bce2d89cff857eb6
来源:牛客网

    public static int findLastNumber(int n,int m){
        if(n<1||m<1) return -1;
        int[] array = new int[n];
        int i = -1,step = 0, count = n;
        while(count>0){   //跳出循环时将最后一个元素也设置为了-1
            i++;          //指向上一个被删除对象的下一个元素。
            if(i>=n) i=0;  //模拟环。
            if(array[i] == -1) continue; //跳过被删除的对象。
            step++;                     //记录已走过的。
            if(step==m) {               //找到待删除的对象。
                array[i]=-1;
                step = 0;
                count--;
            }        
        }
        return i;//返回跳出循环时的i,即最后一个被设置为-1的元素
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值