百度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];
}