携程3.29后端笔试全AC分享(Java实现)
第一题,遍历。
import java.util.*;
public class Main {
private static int cntCircle(String str) {
int res = 0;
for (int i = 0; i < str.length(); ++i) {
char ch = str.charAt(i);
if (ch == '0' || ch == '6' || ch == '9') ++res;
else if (ch == '8') res += 2;
}
return res;
}
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
String str = in.next();
System.out.println(cntCircle(str));
}
}
第二题,贪心。让下标为0, 2, 4, ...(共k个)的位置递增地放最大的k个数,其余下标位置递增地放剩余n-k个数。
import java.util.*;
public class Main {
private static int[] find(int n, int k) {
int ok = n - k + 1, no = 1;
int[] res = new int[n];
for (int i = 0; i < n; ++i) {
if (i % 2 == 0 && i < 2 * k) res[i] = ok++;
else res[i] = no++;
}
return res;
}
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt(), k = in.nextInt();
int[] res = find(n, k);
for (int i = 0; i < n; ++i) {
System.out.print(res[i]);
if (i != n - 1) System.out.print(' ');
else System.out.println();
}
}
}
第三题,查找,找一组x、y,使得(x!-1)*y和n离得尽可能近。用一个Map保存(x!-1),注意用Long(x保存到13就够了,判断标准是x=12时结果不超过n,留一个超过n的备用hhh)。然后遍历x,看与n/(x!-1)相近的两个y(注意排除2)和x算出来的结果,哪个离n更近。
import java.util.*;
public class Main {
private static int[] getRes(long n) {
int x = 1, y = 1, i;
Map<Integer, Long> dp = new HashMap<>();
dp.put(1, 1L);
for (i = 2; dp.get(i - 1) * i <= n; ++i) dp.put(i, dp.get(i - 1) * i);
dp.put(i, dp.get(i - 1) * i);
for (i = 1; dp.containsKey(i); ++i) dp.put(i, dp.get(i) - 1);
for (i = 3; dp.containsKey(i); ++i) {
int j = (int) (n / dp.get(i));
if (getDist(dp.get(i), j, n) < getDist(dp.get(x), y, n)) {
x = i;
y = j;
}
if (j + 1 != 2 && getDist(dp.get(i), j + 1, n) < getDist(dp.get(x), y, n)) {
x = i;
y = j + 1;
}
if (getDist(dp.get(i), j + 2, n) < getDist(dp.get(x), y, n)) {
x = i;
y = j + 2;
}
}
return new int[]{x, y};
}
private static long getDist(long a, long b, long n) {
return Math.abs(a * b - n);
}
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
long n = in.nextLong();
int[] res = getRes(n);
System.out.println(res[0] + " " + res[1]);
}
}
第四题,树(我用图保存的,然后用任意度为1的节点当root)+动态规划+深搜。
在dfs中,传入father代表调用dfs的节点作为父亲,则其余邻接节点是孩子。
dpOn[i]代表下标为i的节点选一条和孩子连接的边涂上颜色以后,以该节点为根的子树得到的权重最大值;
dpOff[i]代表下标为i的节点和所有孩子连接的边均不涂色的情况下,以该节点为根的子树得到的权重最大值。
则状态转移如下思考:
dpOn[i]的状态就是选一个孩子,把连接的边涂色,贡献的权重为边的权重和该孩子不选边涂色的权重最大值w+dpOff[child],其余孩子贡献的权重为选边涂色和不选边涂色的权重最大值;
dpOff[i]的状态就是所有孩子选边涂色和不选边涂色的权重最大值之和。
import java.util.*;
public class Main {
private static long[] dpOn;
private static long[] dpOff;
private static long getMaxWeight(int n, List<Map<Integer, Long>> G) {
if (n == 1) return 0;
int root = 0;
while (G.get(root).size() != 1) ++root;
dpOn = new long[n];
dpOff = new long[n];
dfs(G, root, -1);
return Math.max(dpOn[root], dpOff[root]);
}
private static void dfs(List<Map<Integer, Long>> G, int t, int father) {
if (G.get(t).size() == 1 && G.get(t).containsKey(father)) {
dpOn[t] = 0L;
dpOff[t] = 0L;
} else {
dpOn[t] = 0L;
dpOff[t] = 0L;
long tmp = 0;
for (int v : G.get(t).keySet()) {
if (v == father) continue;
dfs(G, v, t);
tmp += Math.max(dpOn[v], dpOff[v]);
dpOff[t] += Math.max(dpOn[v], dpOff[v]);
}
for (int v : G.get(t).keySet()) {
if (v == father) continue;
dpOn[t] = Math.max(dpOn[t], tmp - Math.max(dpOn[v], dpOff[v]) + dpOff[v] + G.get(t).get(v));
}
}
}
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt();
List<Map<Integer, Long>> G = new ArrayList<>();
for (int i = 0; i < n; ++i) G.add(new HashMap<>());
for (int i = 0; i < n - 1; ++i) {
int a = in.nextInt() - 1, b = in.nextInt() - 1;
long w = in.nextLong();
G.get(a).put(b, w);
G.get(b).put(a, w);
}
System.out.println(getMaxWeight(n, G));
}
}
#笔试复盘##笔试##携程2024暑期实习##携程##算法#
叮咚买菜工作强度 89人发布