zoukankan      html  css  js  c++  java
  • 百度2016校园招聘之编程题解析-软件研发

    百度2016校园招聘之编程题解析-软件研发


    解题思路:解此题须要使用到康托展开,康托展开的公式例如以下

    X=an(n1)!+an1(n2)!++ai(i1)!++a2(21)!+a1(11)!

    公式看不懂没关系,以下以一个样例来解说公式的使用!

    比如:有一个数组S=["a","b","c","d"],它的当中之中的一个个排列是S1=["b","c","d","a"]。如今欲把S1映射成X,须要怎么做呢?按例如以下步骤走起

    X=a43!+a32!+a21!+a10!

    1. 首先计算n,n等于数组S的长度。n=4
    2. 再来计算a4=”b”这个元素在数组["b","c","d","a"]中是第几大的元素。

      ”a”是第0大的元素。”b”是第1大的元素,”c”是第2大的元素,”d”是第3大的元素,所以a4=1

    3. 相同a3=”c”这个元素在数组["c","d","a"]中是第几大的元素。”a”是第0大的元素。”c”是第1大的元素,”d”是第2大的元素,所以a3=1
    4. a2=”d”这个元素在数组["d","a"]中是第几大的元素。”a”是第0大的元素,”d”是第1大的元素,所以a2=1
    5. a1=”a”这个元素在数组["a"]中是第几大的元素。”a”是第0大的元素,所以a1=0
    6. 所以X(S1)=1*3!+1*2!+1*1!+0*0!=9
    7. 注意全部的计算都是依照从0開始的。假设[“a”,”b”,”c”,”d”]算为第1个的话,那么将X(S1)+1即为最后的结果

    Java算法实现

    import java.util.Iterator;
    import java.util.Scanner;
    import java.util.Set;
    import java.util.TreeSet;
    
    /**
     
     * Description:本题须要用到康托展开。其公式为 X=an*(n-1)!+an-1*(n-2)!+...+ai*(i-1)!+...+a2*1!+a1*0!
     
     */
    public class Main {
        //    3
        //    abcdefghijkl
        //    hgebkflacdji
        //    gfkedhjblcia
        static int charLength = 12;//定义字符序列的长度
    
        public static void main(String[] args) {
            Scanner scanner = new Scanner(System.in);
            while (scanner.hasNextInt()) {
                int n = scanner.nextInt();
                String lines[] = new String[n];
                int res[] = new int[n];//存储结果的数组
                for (int i = 0; i < n; i++) {
                    lines[i] = scanner.next();
                    res[i] = calculate(lines[i]);
                }
                for (int s : res) {
                    System.out.println(s);
                }
    
            }
        }
    
        //计算某个字符序列的位次
        private static int calculate(String line) {
            Set<Character> s = new TreeSet<Character>();
            for (char c : line.toCharArray()) {
                s.add(c);
            }
            //存储每个字符在该序列中是第几大的元素。然后将其值存储到counts数组中
            int counts[] = new int[s.size()];
            char[] chars = line.toCharArray();
    
            for (int i = 0; i < chars.length; i++) {
                Iterator<Character> iterator = s.iterator();
                int temp = 0;
                Character next;
                while (iterator.hasNext()) {
                    next = iterator.next();
                    if (next == chars[i]) {
                        counts[i] = temp;
                        s.remove(next);
                        break;
                    } else {
                        temp++;
                    }
                }
            }
            int sum = 1;
            for (int i = 0; i < counts.length; i++) {
                sum = sum + counts[i] * factorial(charLength - i - 1);
            }
            return sum;
        }
    
        //计算阶乘的函数
        private static int factorial(int n) {
            if (n > 1) {
                return n * factorial(n - 1);
            } else {
                return 1;
            }
        }
    }

    解题思路:使用康托逆展开。辗转相除得到的值为这个字符是第几大。这样取出相应位置的字符,然后利用后面的字符覆盖该字符就可以。防止取到反复的字符。取模得到余数之后,反复上述过程。


    比如:已知S=["a","b","c","d"],那么当输入10的时候,或者说X(S1)=9的时候是否能推出S1=["b","c","d","a"]呢?

    X(S1)=a43!+a32!+a21!+a10!=9

    所以问题变成由9是否能唯一地映射出一组a4、a3、a2、a1?首先假设不考虑ai的范围,那么有例如以下:

    13!+12!+11!+00!=9

    03!+42!+11!+00!=9

    03!+32!+31!+00!=9

    03!+22!+51!+00!=9

    ……,可是每个ai事实上是有取值范围的,首先要知道ai表示的含义。其代表在当前剩余的序列中ai是处于第几大的位置。那么满足0<=ai<=i,同一时候a1必定为0,由于最后始终剩余一个元素。

    所以上式中仅仅有第一个满足条件,那么a4=1,a3=1,a2=1。a1=1。推导出S1=["b","c","d","a"]

    Java算法实现

    import java.util.Scanner;
    
    /**
     * 
     * ClassName:Main
     *
     * Description:本题须要用到康托展开,其公式为 X=an*(n-1)!+an-1*(n-2)!+...+ai*(i-1)!+...+a2*1!+a1*0!
     
     */
    public class MainExpand {
        static int charLength = 12;//定义字符序列的长度
    
        public static void main(String[] args) {
            Scanner scanner = new Scanner(System.in);
            while (scanner.hasNextInt()) {
                int n = scanner.nextInt();
                int lines[] = new int[n];
                String res[] = new String[n];//存储结果的数组
                for (int i = 0; i < n; i++) {
                    lines[i] = scanner.nextInt();
                    res[i] = calculate(lines[i] - 1);
                }
                for (String s : res) {
                    System.out.println(s);
                }
            }
    
        }
    
        //计算某个字符序列的位次
        private static String calculate(int line) {
            char alpha[] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l'};
            StringBuilder sb = new StringBuilder();
            for (int i = charLength - 1; i >= 0; i--) {
                int temp = line / factorial(i);
                line = line % factorial(i);
                sb.append(String.valueOf(alpha[temp]));
                for (int j = temp; j < alpha.length - 1; j++) {
                    alpha[j] = alpha[j + 1];
                }
    
            }
            return sb.toString();
        }
    
        //计算阶乘的函数
        private static int factorial(int n) {
            if (n > 1) {
                return n * factorial(n - 1);
            } else {
                return 1;
            }
        }
    }




    解题思路

    1. 将字符串a存储在一个map集合中,以每个字符的ASCII码作为key,以其出现的次数作为value,记为aMap
    2. 遍历字符串b。对于b中的每个字符,假设aMap的key中含有该字符的ASCII码,假设该key相应的value>1,那么将value值减1
    3. 否则value=1的话,那么将该键值对从aMap中移除
    4. 在推断aMap的key是否包括b中的某个字符的时候。仅仅要有一次不包括,那么就说明没有都出现
    5. 否则的话,表示b中的字符在a中都出现过

    Java算法实现:

    import java.util.HashMap;
    import java.util.Map;
    import java.util.Scanner;
    
    /**
     *
     * ClassName:test
     *
     * Description:TODO
     * 
     *
      */
    public class Main {
        public static void main(String[] args) {
            //以某个字符的ASCII码作为key。以其出现的次数作为value
            Map<Integer, Integer> aMap = new HashMap<Integer, Integer>();
    
            Scanner input = new Scanner(System.in);
            while (input.hasNextLine()) {
                String a = input.nextLine();
                String b = input.nextLine();
                char[] chars = a.toCharArray();
                for (char c : chars) {
                    if (aMap.keySet().contains((int) c)) {
                        int temp = aMap.get((int) c);
                        aMap.put((int) c, (temp + 1));
                    } else {
                        aMap.put((int) c, 1);
                    }
                }
    
                char[] chars1 = b.toCharArray();
                boolean flag = true;
                for (char c : chars1) {
                    if (aMap.keySet().contains((int) c)) {
                        int temp = aMap.get((int) c);
                        if (temp == 1) {
                            //说明仅仅有一个
                            aMap.remove((int) c);
                        } else {
                            //说明多过于一个
                            aMap.put((int) c, (temp - 1));
                        }
    
                    } else {
                        flag = false;
                        break;
                    }
    
                }
    
                if (flag) {
                    System.out.println(1);
                } else {
                    System.out.println(0);
                }
                aMap.clear();
            }
        }
    }
    


    解题思路
    须要递推公式,然后用动态规划求解。

    Java算法实现

    import java.text.DecimalFormat;
    import java.util.Scanner;
    
    /**
     * 
     *
     * ClassName:Test3
     *
     * Description:动态规划求解
     * 
     */
    public class Main3 {
        static DecimalFormat dec = new DecimalFormat("0.0000");
        static double v[][];//表示取i个数时和为j的概率
    
        public static void main(String[] args) {
            Scanner input = new Scanner(System.in);
            while (input.hasNextInt()) {
                int n = input.nextInt();
                int a = input.nextInt();
                int b = input.nextInt();
                int x = input.nextInt();
                v = new double[n + 1][x + 1];
                double sum = b - a + 1;
                for (int i = a; i <= b; i++) {
                    v[1][i] = 1.0 / sum;//取1个数和为i的概率
                }
                for (int i = 1; i <= n; i++) {//对n个数进行迭代
                    for (int j = a; j <= b; j++) {//
                        for (int k = 1; k <= x; k++) {
                            if (k >= j) {
    //                            print(v);
    //                            System.out.println();
                                v[i][k] = v[i][k] + v[i - 1][k - j] / sum;
                            }
                        }
                    }
                }
                //输出取n个数和为x的概率
                System.out.println(dec.format(v[n][x]));
    
            }
        }
    
        private static void print(double[][] v) {
            for (int i = 0; i < v.length; i++) {
                for (int j = 0; j < v[i].length; j++) {
                    System.out.print(v[i][j] + "	");
                }
                System.out.println();
    
            }
        }
    }
    仅供參考!!!


  • 相关阅读:
    Python-05知识-01Python优缺点
    Python-02进阶-06代码优化工具
    Python-02进阶-04多进程多线程
    Python-02进阶-03生成器
    Python-02进阶-02装饰器
    Python-01基础-13功能模块
    Python-01基础-12常用命令
    Python-01基础-11基础知识
    console.dir有很多浏览器,系统的兼容性问题,不要随便用!
    微信支付-签名错误
  • 原文地址:https://www.cnblogs.com/slgkaifa/p/7202075.html
Copyright © 2011-2022 走看看