arrays - 使用 swift 优化旅行双循环
问题描述
我使用最小编辑距离算法来查找数组中最相似的字符串。
所以,我必须走双for
循环来比较所有元素。
如果数据足够大,这个算法是低效的。
有没有办法优化?
let data = [
"10000", // count
"asdfqwerty", "asdfzxcvgh", "asdfpoiuyt",
...
]
for i in 1..<data.count {
let string = data[i]
for j in (i + 1)..<data.count {
let newMin = string.minimumEditDistance(other: data[j])
if min >= newMin {
// some logic
}
}
}
extension String {
public func minimumEditDistance(other: String, `default`: Int = 10) -> Int {
let m = self.count
let n = other.count
if m == 0 || n == 0 {
return `default`
}
var matrix = [[Int]](repeating: [Int](repeating: 0, count: n + 1), count: m + 1)
// initialize matrix
for index in 1...m {
// the distance of any first string to an empty second string
matrix[index][0] = index
}
for index in 1...n {
// the distance of any second string to an empty first string
matrix[0][index] = index
}
// compute Levenshtein distance
for (i, selfChar) in self.enumerated() {
for (j, otherChar) in other.enumerated() {
if otherChar == selfChar {
// substitution of equal symbols with cost 0
matrix[i + 1][j + 1] = matrix[i][j]
} else {
// minimum of the cost of insertion, deletion, or substitution
// added to the already computed costs in the corresponding cells
matrix[i + 1][j + 1] = Swift.min(matrix[i][j] + 1, matrix[i + 1][j] + 1, matrix[i][j + 1] + 1)
}
}
}
return matrix[m][n]
}
}
解决方案
您可以通过使用您的minimumEditDistance
作为排序函数对数组进行排序,然后获取第一个或最后一个元素(取决于您如何定义排序)以及您需要什么 - 最小值或最大值来实现所需的行为。它可能会O(N*log(N))
及时运行。这已经比指数要好。
正如@Sultan 提到的,它不适用于所有距离,因为传递性仅适用于度量(定义集合中每个元素之间距离的函数)。您正在使用 Levenstain 距离作为编辑距离算法,这确实是一个度量标准。我提到的解决方案应该有助于在某些情况下进行优化。