zoukankan      html  css  js  c++  java
  • 2018旷视面试

    一、数字组合

    给定一个数组a,其中元素各不相同且都是0~9之间的数字。
    给定一个数字n,要求用数组a中的数字组合出一个大于n的十进制数字来,要求组合出来的数字尽量小,数组a中的元素可以使用多次。

    思路

    从高位往低位扫一遍,贪心使用最小值,如果使用了较大值,剩下的低位一律用最小值进行填充。
    如果找不到合适的,需要回溯使用更大的填充。一旦使用更大的填充之后,剩下的低位使用最小值填充。
    题目中要求组合出大于n的十进制数来,如果最后贪心出来的结果等于n,同样需要回溯一遍。

    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.List;
    import java.util.Random;
    
    public class Main {
    Random r = new Random(0);
    
    int[] generate() {
        int[] b = new int[10];
        for (int i = 0; i < b.length; i++) b[i] = i;
        for (int i = 0; i < b.length; i++) {
            int nex = r.nextInt(b.length - i) + i;
            int temp = b[i];
            b[i] = b[nex];
            b[nex] = temp;
        }
        return Arrays.copyOf(b, r.nextInt(5) + 2);
    }
    
    List<Integer> parse(int n) {
        List<Integer> a = new ArrayList<>(11);
        while (n > 0) {
            a.add(n % 10);
            n /= 10;
        }
        for (int i = 0; i < a.size() / 2; i++) {
            int temp = a.get(i);
            a.set(i, a.get(a.size() - 1 - i));
            a.set(a.size() - 1 - i, temp);
        }
        return a;
    }
    
    int upperEq(int[] a, int x) {
        int l = 0, r = a.length;
        while (l + 1 < r) {
            int mid = (l + r) >> 1;
            if (a[mid] < x) {
                l = mid + 1;
            } else if (a[mid] >= x) {
                r = mid;
            }
        }
        if (l < a.length && a[l] >= x) r = l;
        if (r == a.length) return -1;
        return a[r];
    }
    
    int upper(int[] a, int x) {
        int l = 0, r = a.length;
        while (l + 1 < r) {
            int mid = (l + r) >> 1;
            if (a[mid] <= x) {
                l = mid;
            } else if (a[mid] > x) {
                r = mid;
            }
        }
        if (r == a.length) return -1;
        return a[r];
    }
    
    int pack(List<Integer> a) {
        int s = 0;
        for (int i : a) s = s * 10 + i;
        return s;
    }
    
    int solve(int a[], int n) {
        if (a.length == 0) return -1;
        if (a.length == 1 && a[0] == 0) return -1;
        Arrays.sort(a);
        int first = a[0] == 0 ? a[1] * 10 : a[0] * 10 + a[0];
        List<Integer> bits = parse(n);
        List<Integer> ans = new ArrayList<>(bits);
        //从高位向低位走一遍,如果找到大值,剩余位直接使用最小值填充
        boolean flag = false;
        int i = 0;
        for (; i < bits.size(); i++) {
            //没有找到大值,使用最小上界
            int x = upperEq(a, bits.get(i));
            if (x == -1) {
                break;
            }
            ans.set(i, x);
            if (x != bits.get(i)) {
                flag = true;
                i++;
                break;
            }
        }
        //如果没能成功使用大值填充,需要回溯
        if (!flag) {
            for (i = Math.min(bits.size() - 1, i); i >= 0; i--) {
                int x = upper(a, bits.get(i));
                if (x == -1 && i == 0) {
                    x = first;
                }
                if (x != -1) {//成功找到了大值,可以跳出了
                    ans.set(i, x);
                    i++;
                    break;
                }
            }
        }
        for (; i < bits.size(); i++) {
            ans.set(i, a[0]);//使用最小值进行填充
        }
        return pack(ans);
    }
    
    
    Main() {
        for (int i = 0; i < 10; i++) {
            int[] a = generate();
            int n = r.nextInt(10000000);
            System.out.println(Arrays.toString(a) + " " + n + " " + solve(a, n));
        }
    }
    
    public static void main(String[] args) {
        new Main();
    }
    }
    

    二、max(x,y)的期望

    已知x和y都是0到1上的均匀分布,求max(x,y)的期望。

    下面这种方法只能算是凑对的。
    $int_{0}^{1} 1-m^2 dm=frac{2}{3}$

    $m^2$表示当x<mx<m的概率,用1减去它表示max(x,y)不小于m的概率。

    正经方法如下:
    先求概率分布,再求概率密度函数
    $P(max(x,y)<z)=P(x<z) imes P(y<z)=z^2$
    求导的到概率密度函数$f(z)=2z$
    求积分的到期望$E(z)=int_0^1 f(z)z dz=int_0^1 frac{2z^2}{3}=frac{2}{3}$

    真是忘得一干二净了

    import java.util.*;
    import java.util.stream.Collectors;
    
    public class Main {
    Random r = new Random(0);
    
    
    Main() {
        double s = 0;
        int cnt = 0;
        for (int i = 0; i < 10000; i++) {
            double x = r.nextDouble(), y = r.nextDouble();
            s += Math.max(x, y);
            cnt++;
        }
        System.out.println(s / cnt);
    }
    
    public static void main(String[] args) {
        new Main();
    }
    }
    
  • 相关阅读:
    Java(类与对象)
    Java(数组)动手动脑
    《大道至简》第一章阅读笔记
    Java(接口与继承)动手动脑
    《大道至简》第二章阅读笔记
    Java(String)
    Java动手动脑
    Java程序设计笔记
    控制结构(1)判断控制
    MySQL Cluster 详细配置文件(config.ini)
  • 原文地址:https://www.cnblogs.com/weiyinfu/p/9627459.html
Copyright © 2011-2022 走看看