这么简单!!某高校大学生竟发现约瑟夫出圈问题(取模)不可思议

最经典的出圈问题,你是否也因此而困扰?链表那种方法代码量有点多,在我看来还是取模更加简单,短短几行代码即可轻易实现!

在这里我们使用的是集合来去掉报数的人,主要方法就是根据下标索引来判断删除的位置,最精髓的地方就是当下标大于等于当前人数对总人数取模来获得需要移除的下标

1 .   默认是从第一个人开始报数

import java.util.*;
public class test {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        List<Integer> list=new ArrayList<>();
        int sumPeople=scanner.nextInt();//总共多少人
        int movePeople=scanner.nextInt();//报到几要出圈的那个人
        for ( int i = 1; i <=sumPeople ; i++) {//添加人数
            list.add(i);
        }
        for (int j = movePeople-1; ; j=j+(movePeople-1)) {//比如报2出圈,那么就是下标为1的出圈
            if (list.size()==1) break;//如果最后集合长度为一直接结束(也就是只剩下一个人了)
            if (j>=sumPeople){//j在递增所以当j大于或等于未出圈的人数时我们就要取模来得到下一个要出圈的下标
                j=j%sumPeople;
            }
            System.out.print(list.remove(j)+" ");//remove来移除要出圈的那个人
            sumPeople--;//只要出圈一个人就一定要把还在场的总人数-1
        }
        System.out.print(list.get(0));//最后得到的就是剩余的那一个人
    }
}

下图附上运行结果

 

 下面是详细介绍(确保一次搞明白)

这里举例以总人数5   报数到2

/*
* 5个人  报到2出圈
* 1 2 3 4 5
*第一次:先是2出圈(下标为1  也即是报的数字-1即是我们开始的下标)
*       sumPeople=4    j=2
*       list   1 3 4 5
*第二次:j=2  也就是4出圈
*       sumPeople=3    j=3
*       list   1 3 5
*第三次:j=3 会发现J>=sumPeople  直接用j做下标会越界  所以对sumPeople取模 j的新下标 3%3=0
*       当时的是作为报1  5之后是1报2  1的下标为0  所以取模j就是0  把1去掉
*       sumPeople=2   j=1
*       list   3 5
*第四次:j=1  也就是5出圈
*       sumPeople=1  j=0
*       list   3
* */

附上图文解法:

2 . 从第n个人开始报数

上面那种从一开始的看明白了,从第n个开始那其实是小菜一碟,从第n个开始说白了就是把第n个作为第一个要报数的那个人

好比如原本我们是把报数2的移除当时的下标是1,这时候就可以思维发散一下

如果是从第3个人开始报数  移除报到3的人

1 2 3 4 5

附上图文解释:

 所以当我们把j的初始下标求出来就可以直接修改之,修改如下

再加个输入n即可

 详细代码如下

import java.util.*;
public class test {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        List<Integer> list=new ArrayList<>();
        int sumPeople=scanner.nextInt();//总共多少人
        int movePeople=scanner.nextInt();//报到几要出圈的那个人
        int n=scanner.nextInt();
        for ( int i = 1; i <=sumPeople ; i++) {//添加人数
            list.add(i);
        }
        for (int j = n+movePeople-2; ; j=j+(movePeople-1)) {//n+movePeople-2获取首次下标
            if (list.size()==1) break;//如果最后集合长度为一直接结束(也就是只剩下一个人了)
            if (j>=sumPeople){//j在递增所以当j大于或等于未出圈的人数时我们就要取模来得到下一个要出圈的下标
                j=j%sumPeople;
            }
            System.out.print(list.remove(j)+" ");//remove来移除要出圈的那个人
            sumPeople--;//只要出圈一个人就一定要把还在场的总人数-1
        }
        System.out.print(list.get(0));//最后得到的就是剩余的那一个人
    }
}

附上运行结果:

 

 制作不易,如果帮到了你,给个赞!!!

给个鼓励!!

谢谢!!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值