Java实现约瑟夫环问题

烈酒焚心 提交于 2019-11-28 19:25:25

有朋友去浦发面试,因为我们是相同岗位,为了查漏补缺,便问了一下他们的机试题目。

机试考3道编程,前两道很水,最后一道他说有点麻烦,没有AC。我自己也尝试着码了一下,然后发现还是得需要耐心。

在此,我列出了三种方法,以供大家参考。

其中包括标号从0 开始的(0....(N-1)),和标号从1开始的(1....N))两个版本。

先简单说一下我的思路,前两种方法就是模拟整个过程:

1. 标号从1开始:

用动态数组存储数据,一个大循环就是数组不为空;然后利用 target = (target + k)%list.size(); 求出数组下标,对list.size()取模是为了不让target越界;那么得到的target的范围就是【0,list.size()】,然后就打印 list.get(target-1) ,所以,为了不越界,需要判断  target!=0 ,然后,再将该元素移除 list.remove(target-1);  ,最后再将下标自减1(关于为什么将下标再减一,下面第2种方法中有解释)。如果 target==0 的话,那么就打印数组中最后一位 list.get(list.size()-1) ,然后再移除该元素即可。

代码如下:

 

private static void lastPeople(int total, int k) {
        //初始化人数,人数排号从1开始;
        List<Integer> list = new ArrayList<Integer>();
        for (int i = 1; i <= total; i++) {
            list.add(i);
        }
        //从第target(数组下标)个开始重新数数;
        int target = 0;
        while (!list.isEmpty()) {
            target = (target + k)%list.size();
            //当target=0时,target-1就是-1了,数组越界,其意思就是返回倒数第一个元素,即list.size()-1;
            if (target != 0) {
                System.out.print(list.get(target-1)+" ");
                list.remove(target-1);
                target--;
            }else {
                System.out.print(list.get(list.size()-1)+" ");
                list.remove(list.size()-1);
            }
        }
        
    }

 

 

2. 标号从0开始:

同样的,用动态数组存储数据,一个大循环就是数组不为空;用 i 记录已走过的整个数组下标的最后一位(关于这句话,大家可能不太理解,意思就是比如数组[1,2,3,4,5,6],当遍历到元素4时,下标为3,然后把4移除,下标自减,让其改为2,指向元素3,而不是指向还未遍历到的元素5);以count计数,到第k个就删去该元素,并且置count=0,i-- 使得下标回退一步。

代码如下:

private static void lastPeople1(int total, int k) {
        //初始化人数
        List<Integer> list = new ArrayList<Integer>();
        for (int i = 0; i < total; i++) {
            list.add(i);
        }
        int i = -1;//记录整个序号下标
        int count = 0;//记录第几个,是否到达第k个;
        while (list.size() != 0) {
            ++i;
            if (i == list.size()) {
                i = 0;
            }
            ++count;
            if (count == k) {
                System.out.print(list.get(i) +" ");
                list.remove(i);
                count=0;
                --i;
            }
        }
        
    }

 

3. 第三种方法是我从网上找来的,但是该方法不能打印整个过程,只能选择出最后一位被枪毙的人是谁。是用数学规律解的,本人表示服气。

推出的递归公式是: F(i)=F(i-1)+ k  ,为了防止数组越界,需要取模  F(i)=(F(i-1)+ k)%i  。

代码如下:

private static void lastPeople2(int n, int k) {
    int res = 0;
    for (int i = 2; i <= n; i++) {
        res = (res + k)%i;
    }
    System.out.print((res+1)+" ");
}

 

三种方法输出结果如下:

 

以上我都是用动态数组arraylist来存储数据的,我在网上查到还有用队列解决的,方法也很好,在这里我就不多说了,详见参考4.

 

 

Over...

 

参考:

1.  约瑟夫环问题

2. 约瑟夫环Java实现

3. Java实现约瑟夫环问题

4. 数据结构(二)java解决约瑟夫环的两种方法(数组和队列)

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!