问题描述
某特种部队采用了一套性格密码机制来筛选执行特定任务的最佳士兵,该机制的规则如下:
- 每个人的性格可以通过
M个维度来描述,每个维度分为A, B, C, D, E五种类型。 - 同一维度内,字母距离越近,性格类型差异越小,匹配程度越高。比如,A 和 B 的差异为
1,A 和 D 的差异为3。 - 其中
AE、BD、CE、BE为不相容性格类型,差异值设为无穷大(无法匹配)。 - 如果某一维度存在不相容性格类型,则表示两个士兵性格完全不匹配。
- 对于符合匹配条件的士兵,差异值总和越小表示匹配程度越高。
现在,有一个重要的机密任务,要求找到最匹配该任务所需性格密码的士兵。你需要编写一个算法,帮助部队找到符合条件的最佳人选。
m表示性格密码的维度。n表示备选特种兵的数量。target是代表任务的性格密码。array是一个包含n个元素的列表,每个元素为M位的性格密码。
测试样例
样例1:
输入:
m = 6, n = 3, target = "ABCDEA", array = ["AAAAAA", "BBBBBB", "ABDDEB"]
输出:'ABDDEB'
样例2:
输入:
m = 5, n = 4, target = "ABCED", array = ["ABCDE", "BCDEA", "ABDCE", "EDCBA"]
输出:'ABCDE'
样例3:
输入:
m = 4, n = 4, target = "AEBC", array = ["ACDC", "BBDC", "EBCB", "BBBB"]
输出:'None'
解题思路
先让我们看看MarsCode的思路,如下:
-
理解性格差异计算:
-
每个维度的性格类型有
A, B, C, D, E,我们需要计算两个性格类型之间的差异。 -
差异值的计算规则如下:
A和B的差异为1,A和D的差异为3。AE、BD、CE、BE为不相容性格类型,差异值设为无穷大(无法匹配)。
-
-
计算总差异值:
- 对于每个候选士兵,计算其与目标性格密码在每个维度上的差异值。
- 如果某个维度存在不相容性格类型,则直接返回
None。 - 否则,计算总差异值,并找到差异值最小的士兵。
-
返回最佳匹配:
- 如果所有士兵都存在不相容性格类型,则返回
None。 - 否则,返回差异值最小的士兵的性格密码。
- 如果所有士兵都存在不相容性格类型,则返回
具体代码如下:
def solution(m, n, target, array):
# 定义性格差异值的映射
diff_map = {
'A': {'A': 0, 'B': 1, 'C': 2, 'D': 3, 'E': float('inf')},
'B': {'A': 1, 'B': 0, 'C': 1, 'D': float('inf'), 'E': 2},
'C': {'A': 2, 'B': 1, 'C': 0, 'D': 1, 'E': float('inf')},
'D': {'A': 3, 'B': float('inf'), 'C': 1, 'D': 0, 'E': 1},
'E': {'A': float('inf'), 'B': 2, 'C': float('inf'), 'D': 1, 'E': 0}
}
# 初始化最小差异值为无穷大
min_diff = float('inf')
best_match = None
# 遍历每个候选士兵
for soldier in array:
total_diff = 0
incompatible = False
# 计算当前士兵与目标性格密码的总差异值
for i in range(m):
diff = diff_map[target[i]][soldier[i]]
if diff == float('inf'):
incompatible = True
break
total_diff += diff
# 如果存在不相容性格类型,跳过该士兵
if incompatible:
continue
# 更新最佳匹配
if total_diff < min_diff:
min_diff = total_diff
best_match = soldier
return best_match
if __name__ == "__main__":
# Add your test cases here
matrix = [
"AAAAAA", "BBBBBB", "ABDDEB"
]
print(solution(6, 3, "ABCDEA", matrix) == "ABDDEB")
整体思路大致是对的,但是个人觉得性格差异值那边可以优化一下,还有测试案例3错误了
发现是他没有把BE的差异值设成无穷大,于是我重写了性格差异函数
def calculate_diff(c1, c2):
"""计算两个性格类型的差异值。"""
incompatible_pairs = [('A', 'E'), ('B', 'D'), ('C', 'E'), ('B', 'E')]
if (c1, c2) in incompatible_pairs or (c2, c1) in incompatible_pairs:
return float('inf')
return abs(ord(c1) - ord(c2))
然后再次提交发现,第9个测试案例错误
计算发现这两个差异是一样大的,所以说如果差异值一样则都要输出,于是我把best_candidate从值变成了列表,后续如果相等的也加入列表。
if total_diff < min_diff:
min_diff = total_diff
best_candidates = [candidate] # 开始一个新的列表
elif total_diff == min_diff:
best_candidates.append(candidate) # 添加到现有的最佳候选人列表中
此时又出现了新的问题,如果全都是差异无限也全输出了
于是加上了差异不能无限大,代码如下:
if total_diff < min_diff:
min_diff = total_diff
best_candidates = [candidate] # 开始一个新的列表
elif total_diff == min_diff and min_diff!=float('inf'):
best_candidates.append(candidate) # 添加到现有的最佳候选人列表中
此时终于通过了
最终代码如下:
def calculate_diff(c1, c2):
"""计算两个性格类型的差异值。"""
incompatible_pairs = [('A', 'E'), ('B', 'D'), ('C', 'E'), ('B', 'E')]
if (c1, c2) in incompatible_pairs or (c2, c1) in incompatible_pairs:
return float('inf')
return abs(ord(c1) - ord(c2))
def solution(m, n, target, array):
min_diff = float('inf')
best_candidates = []
for candidate in array:
total_diff = 0
for i in range(m):
diff = calculate_diff(target[i], candidate[i])
if diff == float('inf'):
total_diff = float('inf')
break
total_diff += diff
if total_diff < min_diff:
min_diff = total_diff
best_candidates = [candidate] # 开始一个新的列表
elif total_diff == min_diff and min_diff!=float('inf'):
best_candidates.append(candidate) # 添加到现有的最佳候选人列表中
if not best_candidates:
return 'None'
return ' '.join(best_candidates)
if __name__ == "__main__":
# Add your test cases here
matrix = [
"AAAAAA", "BBBBBB", "ABDDEB"
]
print(solution(6, 3, "ABCDEA", matrix) == "ABDDEB")