题解:寻找最匹配士兵
题目分析
我们需要为目标任务找到一个士兵性格密码,匹配规则分为以下几步:
- 每个性格密码有 (M) 维。
- 每维的匹配程度通过字母距离计算,差异越小越匹配。
- 如果某一维性格不兼容(如 AE, BD 等),该士兵直接排除。
- 找到所有符合条件且差异最小的士兵密码。
代码实现
以下是实现代码,并带有详细讲解。
import java.util.*;
public class Main {
// 计算两个字符的差异值
private static int dist(char x, char y) {
List<String> incompatibility = Arrays.asList("AE", "BD", "CE", "BE");
// 构造不兼容对
String pair = "" + x + y;
String reversePair = "" + y + x;
// 如果是无效组合,返回无穷大
if (incompatibility.contains(pair) || incompatibility.contains(reversePair)) {
return Integer.MAX_VALUE;
}
// 否则返回差异值
return Math.abs(x - y);
}
public static String solution(int m, int n, String target, String[] array) {
// 最小差异值记录
int bestDist = Integer.MAX_VALUE;
List<String> bestMatches = new ArrayList<>();
for (String s : array) {
int totalDist = 0;
boolean isValid = true; // 判断当前士兵是否有效
for (int i = 0; i < m; i++) {
int currDist = dist(target.charAt(i), s.charAt(i));
// 如果当前维度不匹配,直接退出
if (currDist == Integer.MAX_VALUE) {
isValid = false;
break;
}
totalDist += currDist;
}
// 如果当前士兵有效,比较差异值
if (isValid) {
if (totalDist < bestDist) {
bestDist = totalDist;
bestMatches.clear();
bestMatches.add(s);
} else if (totalDist == bestDist) {
bestMatches.add(s);
}
}
}
// 如果没有找到合适的士兵
if (bestMatches.isEmpty()) {
return "None";
}
// 返回所有最优士兵密码,以空格分隔
return String.join(" ", bestMatches);
}
public static void main(String[] args) {
// 测试样例
String[] matrix1 = {"AAAAAA", "BBBBBB", "ABDDEB"};
System.out.println(solution(6, 3, "ABCDEA", matrix1)); // 输出:ABDDEB
String[] matrix2 = {"ABCDE", "BCDEA", "ABDCE", "EDCBA"};
System.out.println(solution(5, 4, "ABCED", matrix2)); // 输出:ABCDE
String[] matrix3 = {"ACDC", "BBDC", "EBCB", "BBBB"};
System.out.println(solution(4, 4, "AEBC", matrix3)); // 输出:None
}
}
代码讲解
-
dist方法- 接收两个字符,判断是否存在不兼容关系。
- 如果不兼容,返回无穷大 (
Integer.MAX_VALUE);否则返回字母差值。
-
遍历候选密码数组
- 对于每个候选密码,逐维度计算差异值。
- 如果某一维度不匹配,直接跳过该密码。
-
记录最优解
- 维护当前最小差异值
bestDist和对应的最优密码列表bestMatches。 - 如果发现更小的差异值,更新结果;如果差异值相同,将密码加入列表。
- 维护当前最小差异值
-
结果拼接
- 如果没有符合条件的密码,返回
"None"。 - 否则将最优密码列表用空格拼接返回。
- 如果没有符合条件的密码,返回
改进方案
为了让代码更整洁,可以将兼容性检查逻辑与差异值计算逻辑分离,同时减少 StringBuilder 操作。
改进后的dist方法:
private static final Set<String> INCOMPATIBILITY = new HashSet<>(Arrays.asList("AE", "BD", "CE", "BE"));
private static int dist(char x, char y) {
if (x == y) return 0;
if (INCOMPATIBILITY.contains("" + x + y) || INCOMPATIBILITY.contains("" + y + x)) {
return Integer.MAX_VALUE;
}
return Math.abs(x - y);
}
改进后的匹配逻辑:
boolean isValid = true;
for (int i = 0; i < m && isValid; i++) {
int currDist = dist(target.charAt(i), s.charAt(i));
if (currDist == Integer.MAX_VALUE) isValid = false;
else totalDist += currDist;
}
使用String.join优化拼接:
return bestMatches.isEmpty() ? "None" : String.join(" ", bestMatches);
优化点总结
- 使用
Set加速不兼容对的查找。 - 将拼接逻辑抽离为标准库函数。
- 利用条件短路减少冗余代码,提升可读性。
以上改进使代码结构更清晰,同时提升了性能和可维护性。