丢手绢问题

来源:互联网 发布:水冶豫广网络 编辑:程序博客网 时间:2024/06/10 09:30

问题描述:
N个人围成一圈,从第一个开始报数,报到3的倍数将被杀掉,最后剩下一个,其余人都将被杀掉。例如N=7,被杀掉的人的序号为3,6,2,7,5,1。最后剩下4号。

本人非计算机专业没学过算法,如果写的有问题还请指正,废话不多说直接上代码

/** * 丢手绢问题 * N个人围成一个圈,编号为1~N,从第一号开始报数,报到3的倍数的人离开,一直数下去,直到最后只有一个人,求此人编号 * @author 蚂蚁看星空 * */public class CycleGame {    public static void main(String[] args) {        int n = 20000;        method1(n);        method2(n);    }    /**     * 算法2     * 思路:用一个单独的计数器,有效循环一次计一次,计数器为3的倍数时清空对应元素,     *             数组遍历结束后,遍历索引清0,重新开始遍历效果等同于外面嵌套一个while(true),     *           当有效号码只有一个时结束循环     * @param n     */    public static void method2(int n){        long s = System.currentTimeMillis();        int[] nums = new int[n];        //循环计数        int count = 0;        //剩余号码个数        int less = n;        for (int i = 0; i < n; i++) {            nums[i] = (i+1);        }        for(int i = 0; i < nums.length; i++){            //号码为0的是被清除的不在循环计算范围内            if(nums[i] !=0){                count++;            }            if(count != 0 && count%3 == 0){                count = 0;                //将清除的号码至0,这里也可以直接删除元素,但数组长度是不可变的,懒得写删除                nums[i] = 0;                less--;                if(less <= 1){                    break;                }            }            if(i == nums.length -1){                i = -1;            }        }        for(int i = 0; i < nums.length; i++){            if(nums[i] !=0)                System.out.println("最后号码:" + (i+1));        }        long e = System.currentTimeMillis();        System.out.println("算法2用时:"+ (e-s)+"毫秒");    }    /**     * 算法1     * 思路: 用list装载号码,遍历时将被3整除的号码清空,到整个循环的后面不再有可能出现被3整除的号码时,     *         用一个临时的list添加后续的号码,并在原list中删除,然后将原list中的剩余号码按顺序加入新的list中,     *         再遍历新的list,这样新list的第元素顺序和计数顺序就是一致的,到最后只剩两个号码时,那第一个号码肯定就不满足条件了     * @param n     */    public static void method1(int n){        long s = System.currentTimeMillis();        List<Integer> nums = new ArrayList<Integer>();        for (int i = 1; i <= n; i++) {            nums.add(i);        }        List<Integer> list = new ArrayList<Integer>();        while (true) {            //如果只剩下2个号码,那第1个号码肯定出局            if (nums.size() < 3) {                System.out.println("最后号码:" + nums.get(1));                break;            }            for (int i = 1; i <= nums.size(); i++) {                if (i % 3 == 0) {//将被3整除的编码清0                    nums.set(i - 1, 0);                } else {                    //如果不被3整除,且剩余元素不超过2个,则添加至一个新的集合,重新生成顺序                    if (nums.size() % 3 != 0 && nums.size() - i < 2) {                        list.add(nums.get(i - 1));                        nums.set(i - 1, 0);                    }                }            }            for (int i = 1; i <= nums.size(); i++) {                if (nums.get(i - 1) != 0) {                    list.add(nums.get(i - 1));                }            }            nums.clear();            nums.addAll(list);            list.clear();        }        long e = System.currentTimeMillis();        System.out.println("算法1用时:"+ (e-s)+"毫秒");    }}
1 0
原创粉丝点击