蓝桥杯真题:abcdefghijklmnopqrs循环106次,重复删奇数位字符,最终剩下的字符?

晚上有群友出题:

abcdefghijklmnopqrs循环106次,组成新的2014个字符的字符串,然后删掉奇数位的字符,再次组成新的字符,在删掉奇数字符,最后剩下一个字符,这个字符是啥


先用笨办法,模拟每一次删除操作,直到只剩下最后一个值

第一个元素的索引是0,本来应该依次删除 2,但是删了0之后,所有的位置都往前移了一位,所以接下来要删除的索引是1。所以i只需要自增1。

import java.util.*;
public class Test {
    public static void main(String[] args){        
        List<Character> list = new ArrayList<Character>();
        String s = "abcdefghijklmnopqrs";
        for(int i = 1; i <= 106; i++){
            for(int j = 0; j < s.length(); j++){
                list.add(s.charAt(j));
            }
        }
        long start = System.nanoTime();
        while(list.size() > 1){            
            for(int i = 0; i < list.size(); i++){
                list.remove(i);            
            }
        }
        System.out.println("用时:" + (System.nanoTime() - start) + "纳秒");
        System.out.println(list.get(0));
    }
}
------Output------

用时:1711791纳秒
q


上面是最笨的办法,List的查找和删除消耗了大量时间。改进了一下思路:

原始的索引是:
0 1 2 3 4 5  6  7  8  9 10 11 12.......
删了一次后,索引是:
1 3 5 7 9 11 13 15 17 19...........
再删,索引是:
3 7 11 15 19.....
继续删,索引是:
7 15 .....
当删得只剩下一个数时,是最终结果。而这个唯一的数,同时也是剩下的第一个数,所以可以找第一个数的索引有什么规律。
0*2+1=1,1*2+1=3,3*2+1=7....
这样一直找下去,直到找出最后一个小于2014的值,就是最后剩下的索引值。

public class T3{
    public static void main(String[] args){
        String s = "abcdefghijklmnopqrs";
        StringBuilder sb = new StringBuilder();
        for(int i = 1; i <= 106; i++){
            sb.append(s);
        }
        //下面开始查找
        long start = System.nanoTime();
        int t = 0;
        while((t*2+1)<= 2014){
            t = t*2+1;
        }
        System.out.println((System.nanoTime()-start) + "纳秒");
        System.out.println(sb.charAt(t));
    }
}
------Output------

3421纳秒
q


做完又百度了一下,发现有位大神更牛:

就是第1024位置的字母"q"
第一次留下的是2的倍数,第二次留下的是4的倍数,第三次就是8的倍数。

代码的话,只要一句话。

return ('a' + 1024%19-1);

这位大神的想法前半部分和我是一样的,只是他从1开始编号,而我从0开始编号。后面取出字母的方法更简单直接,佩服。

版权声明:本文为博主原创文章,未经博主允许不得转载。

posted @ 2014-12-17 00:36  包清骏  阅读(648)  评论(0编辑  收藏  举报