【剑指Offer 45】圆圈中最后剩下的数字(约瑟夫环问题)

题目:0, 1, … , n-1 这n个数字排成一个圈圈,从数字0开始每次从圆圏里删除第m个数字。求出这个圈圈里剩下的最后一个数字。

代码如下:

package demo;

import java.util.LinkedList;
import java.util.List;

/**
 * 圆圈中最后剩下的数字(约瑟夫环问题)
 * 
 * @author xiangdonglee
 *
 */
public class Test45 {
    /**
     * 经典解法:用环形链表模拟圆圈。 创建一个共有n个结点的环形链表,然后每次在这个链表中删除第m个结点。
     * 
     * @param n
     * @param m
     * @return
     */
    public static int lastRemaining(int n, int m) {
        if (n < 1 || m < 1) {
            return -1;
        }
        List<Integer> list = new LinkedList<>();
        for (int i = 0; i < n; i++) {
            list.add(i);
        }
        // 要删除元素的位置
        int index = 0;
        // 开始计数的位置
        int start = 0;
        while (list.size() > 1) {
            // 只要移动m-1次就可以移动到下一个要删除的元素上
            for (int i = 1; i < m; i++) {
                index = (index + 1) % list.size(); // [A]
            }
            list.remove(index);
            /**
             * 确保index指向每一轮的第一个位置
             * 
             * [A]已结能够保证其正确性了,因此下面这3行可以不用写
             */
            // if(index==list.size()) {
            // index=0;
            // }
        }
        return list.get(0);
    }

    /**
     * 数学分析法
     * 
     * @param n
     * @param m
     * @return
     */
    public static int lastRemaining2(int n, int m) {
        if (n < 1 || m < 1) {
            return -1;
        }
        int last = 0;
        for (int i = 2; i <= n; i++) {
            last = (last + m) % i;
        }
        return last;
    }

    public static void main(String[] args) {
        test1();
        System.out.println();
        test2();
    }

    private static void test1() {
        System.out.println(lastRemaining(5, 3));
        System.out.println(lastRemaining(5, 2));
        System.out.println(lastRemaining(6, 7));
        System.out.println(lastRemaining(6, 6));
        System.out.println(lastRemaining(0, 0));
    }

    private static void test2() {
        System.out.println(lastRemaining2(5, 3));
        System.out.println(lastRemaining2(5, 2));
        System.out.println(lastRemaining2(6, 7));
        System.out.println(lastRemaining2(6, 6));
        System.out.println(lastRemaining2(0, 0));
    }
}
运行结果

来源:http://blog.csdn.net/derrantcm/article/details/46798717

推荐阅读更多精彩内容

  • 题目:0,1,2,...,n-1这n个数字排成一个圆圈,从数字0开始每次从这个圆圈里删除第m个数字。求出这个圆圈里...
    qmss阅读 181评论 0 0
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 166,652评论 24 703
  • 题目:0, 1, … , n-1 这 n 个数字排成一个圈圈,从数字 0 开始每次从圆圏里删除第 m 个数字。求出...
    jacky123阅读 1,115评论 0 1
  • 教你如何迅速秒杀掉:99%的海量数据处理面试题 本文经过大量细致的优化后,收录于我的新书《编程之法》第六章中,新书...
    Helen_Cat阅读 6,869评论 0 39
  • 从别人的批评中得到自己想要的东西。以目标结果为导向
    fenghua_sjtu阅读 180评论 0 0
  • 这几天女儿丢三拉四的毛病有点犯了 ,昨天手抄报落后一天,今天漫画,不过今天晚上她坚决的把画的基础画出来了。这也许跟...
    幸福_216b阅读 79评论 0 0
  • 跳过俗不可耐的影片制作介绍,我们直奔主题。因为我相信大家都知道,不知道也没关系,我相信大家也没兴趣,有兴趣不知道也...
    森豪阅读 864评论 0 0
  • 有人说红颜薄命, 这是事实, 但不是所有的红颜, 而是几个特例而已。 《红楼梦》中美女大多如此, 社会使之然也, ...
    旖旎i阅读 72评论 6 9