微软 软开8.19笔试
如无意外感觉终于AK了,只不过第二题自己实现有点复杂,不知道会不会超时呢。。
第一题 修道路
思路:x坐标数组排序+贪心
public int solution(int[] X, int[] Y, int W) {
int length = X.length;
// 定义数组记录修复状态
boolean[] used = new boolean[length];
// 只需要关注横坐标 对其进行排序
Arrays.sort(X);
// 记录结果
int result = 0;
// 遍历一次整个数组
for (int i = 0;i < length;i++) {
// 如果已经修复 则跳过
if (used[i]) {
continue;
}
// 修复当前坑
used[i] = true;
result++;
int cover = X[i]+ W;
// 把在覆盖范围内的坑也修复
for (int j = i + 1;j < length;j++) {
if (X[j] <= cover) {
used[j] = true;
}else {
break;
}
}
}
// 返回结果
return result;
} 第二题 根据给出的字符串(只有0-9)构建最大的回文数字串 "3818286989" -> "9886889"
思路:想不到啥好办法,只能统计一次所有数字出现的次数 出现超过2次的数中按序构建。如果有更好办法的话请指教。
public String solution(String S) {
// 定义一个map存储数字对应出现的次数
Map<Character, Integer> countMap = new HashMap<>();
// 定义一个list存储出现次数大于等于1的数字
List<Character> countList = new ArrayList<>();
// 定义一个Set去存储出现过的数字,方便后续取出只出现一次的最大数
Set<Character> allSet = new HashSet<>();
// 创建结果集
StringBuilder sb = new StringBuilder();
// 遍历一次字符串进行初始化统计
for (char c : S.toCharArray()) {
countMap.put(c, countMap.getOrDefault(c, 0) + 1);
allSet.add(c);
if (countMap.get(c) >= 2) {
countList.add(c);
}
}
// 对countList排序
countList.sort((a, b) -> b - a);
for (char c : countList) {
while (countMap.get(c) >= 2) {
// 使用掉就要减去
countMap.put(c, countMap.get(c) - 2);
if (c == '0' && sb.length() == 0) {
continue;
}
sb.append(c);
}
}
String reverse = new StringBuilder(sb.toString()).reverse().toString();
// 对Set进行排序
List<Character> set = new ArrayList<>(allSet);
set.sort((a, b) -> b - a);
for (Character c : set) {
if (countMap.get(c) > 0) {
sb.append(c);
break;
}
}
sb.append(reverse);
return sb.toString().equals("") ? "0" : sb.toString();
} 思路:由于0是最终的终点,因此可以看成根节点,最终整个道路就是一个多叉树。我采用了递归的方法,每个节点return当前节点的人数,并且在遍历的过程中记录油耗。(难点就在于给出的不是一颗树,而是两个数组,并且边界和细节真的特别特别多,这道题一共写了将近30分钟。。)
public int solution(int[] A, int[] B) {
// 找到与0相接的结点
List<Integer> connectList = find(0, A, B);
for (int i : connectList) {
// 分别递归
dfs(0, i, A, B);
// 每个节点过来都需要汽油
fuel++;
}
return fuel;
}
public int dfs(int parent, int now, int[] A, int[] B) {
// 找到当前节点的相接节点
List<Integer> connectList = find(now, A, B);
// 默认一个人
int people = 1;
for (int i : connectList) {
// 如果与父节点相同则不需要计算
if (i == parent) {
continue;
}
// 获取子节点的人数
int result = dfs(now, i, A, B);
// 每个节点过来都需要汽油
fuel++;
// 人数++
people += result;
}
// 大于5个人的时候需要加汽油
if (people > 5) {
fuel += (people / 5) - 1;
}
return people;
}
// 用于寻找相接的结点
public List<Integer> find(int target, int[] A, int[] B) {
List<Integer> list = new ArrayList<>();
for (int i = 0;i < A.length;i++) {
if (A[i] == target) {
list.add(B[i]);
}
if (B[i] == target) {
list.add(A[i]);
}
}
return list;
} 