Josephus问题(约瑟夫问题)链表的实现

Josephus问题(约瑟夫问题)链表的实现

Josephus问题,下面的游戏:N个人编号从1到N,围坐成一个圈.从1好开始传递一个热土豆.经过M次传递后,拿着热土豆的人被清楚离座,围坐的圈缩紧,由坐在被清除的人后面的人拿着热土豆,继续进行游戏.最后剩下的人取胜.因此,如果M=0和N=5,则游戏人依序被清除,5号游戏人获胜.如果M=1和N=5,那么被清除的人的顺序是2,4,1,5

下面是通过LinkedList实现:

private static void josephus(int m, int n){
        LinkedList<Integer> list = new LinkedList<Integer>();
        for(int i = 1 ; i <= m; i++){
            list.add(i);
        }
        int loc = 0; // 起始位置

        while (true) {
            for (Integer x:list)
                System.out.print(x + " ");
            System.out.println();
            int size = list.size();
            if (size == 1) {
                System.out.println(list.get(0).toString() + ", won!");
                return;
            } else {
                int gap = n % size;
                loc += gap;
                if(loc >= size){
                    loc -= size;
                }
                ListIterator it = list.listIterator(loc);
                if (it.hasNext()) {
//                    it.next();
                      System.out.println("next remove : " + it.next().toString()); //必须调用到it.next()方法
                }
                it.remove();
            }


        }

    }

另一种优化后的算法:

    public static void pass(int m, int n) {
        int i, j, gap, numLeft;
        ArrayList<Integer> L = new ArrayList<Integer>();
        for (i = 1; i <= m; i++)
            L.add(i);
        ListIterator<Integer> iter = L.listIterator();
        Integer item = 0;
        numLeft = m;
        for (i = 0; i < m; i++) {
            gap = n % numLeft;
            if (gap <= numLeft / 2) {
                if (iter.hasNext())
                    item = iter.next();
                for (j = 0; j < gap; j++) {
                    if (!iter.hasNext())
                        iter = L.listIterator();
                    item = iter.next();
                }
            } else {
                for (j = 0; j < numLeft - gap; j++) {
                    if (!iter.hasPrevious())
                        iter = L.listIterator(L.size());
                    item = iter.previous();
                }
            }
            System.out.print("removed " + item + " ");
            iter.remove();
            if (!iter.hasNext())
                iter = L.listIterator();
            System.out.println();
            for (Integer x:L)
                System.out.print(x + " ");
            numLeft--;
        }
    }

主要是减少了listIterator的调用次数,只有在边界的时候才调用.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值