百度3.30笔试

3月29,下午七点开始的,过了2.6道,复盘

第一题

给出n,找两个数a,b(1<=a<b<=n),使得a和b的最小公倍数,最大共因数,差值最大
思路:res = a * b / gcd(a,b) - gcd(a, b),使得ab最大,gcd(a,b)最小,所以a取n,b取(n-1),两者互质,res = n(n-1)-1

第二题

n个数字,每次取出一个最大的数字减去n,其余数字+1,一致重复直到最大的数小于n,最少操作多少次
思路:贪心,每次竟可能多的降所有大于等于n的数字,然后递归

    private static int solve2(int n, long[] A) {
        long[] t = new long[n];
        int time = 0;
        for(int i = 0; i < n; i++) {
            if(A[i] >= n) {
                t[i] = A[i] / n;
                time += t[i];
                A[i] %= n;
            }
        }
        boolean flag = true;
        for(int i = 0; i < n; i++) {
            A[i] += time - t[i];
            if(A[i] >= n) flag = false;
        }
        return flag ? time : time + solve2(n, A);
    }

第三题

一棵树(无换),每个节点都有权重,求一条最长的路径,使得路径上的严格递增。
思路:对每个节点DFS,用数组保存结果,记忆化搜索

    private static int solve3(int n, int[][] edges, int[] weight) {
        ArrayList<Integer>[] graph = new ArrayList[n+1];
        for(int i = 0; i <= n; i++) graph[i] = new ArrayList<Integer>();
        for(int[] e : edges) {
            graph[e[0]].add(e[1]);
            graph[e[1]].add(e[0]);
        }
        int[] dp = new int[n+1];
        Arrays.fill(dp, -1);
        int res = 0;
        for(int i = 1; i <= n; i++) {
            res = Math.max(res, dfs(dp, i, graph, weight) + 1);
        }
        return res;
    }

    private static int dfs(int[] dp, int i, ArrayList<Integer>[] graph, int[] weight) {
        dp[i] = 0;
        for(int j = 1; j <= graph[i].size(); j++) {
            int nextId = graph[i].get(j-1);
            if(dp[nextId] == -1 && weight[i] < weight[nextId]) {
                dp[i] = Math.max(dp[i], dfs(dp, nextId, graph, weight) + 1);
            }
        }
        return dp[i];
    }
posted @ 2020-03-30 19:02  冰糖ryj  阅读(148)  评论(2编辑  收藏  举报