【发布时间】:2018-08-17 04:27:54
【问题描述】:
这个问题与我在工作中遇到的当前问题有关,但由于它相当广泛,我试图将其表述为更多的面试问题以鼓励讨论。
假设我们有以下两个字符串:
str1 = 'helloworld'
str2 = 'helloldwor'
我希望能够比较 str1 和 str2 并确定 str2 中的哪些字符是乱序的,假设 str1 是“正确的”。还可以假设 str2 中的所有字符都与 str1 相同(str2 只是 str1 的混杂版本)。
编辑:在这种情况下,我会说“ld”出现故障。我将“无序”子字符串定义为 str2 的最小子字符串,如果将其移动到与 str1 中的子字符串相同的位置,将使 str1 == str2。
这个问题一直困扰着我很长时间,因为它很容易从视觉上弄清楚,但我正在努力将它变成某种算法。
我的尝试:
def get_ooo(str1, str2):
#for potential options
local_set = Set()
#Loop from len(str1) to 1, splitting str2 by i to cover all possible substrings of str2
split_size = len(str1)
for i in range(len(str1),1,-1):
print 'Iteration #' + str(len(str1) - split_size)
#Try to find all substrings of str2 of length 'i' in str1
for j in range(0,len(str1)-i):
if str1.find(mid(str2,j,i)) < 0:
#Failed to find substring in str1
#Add to our local_set if it is a substring of all other failed substrings
intersect = True
for k in local_set:
if k.find(mid(str2,j,i)) < 0:
intersect = False
#If substring was a substring of all other failed substrings
if intersect:
#Add to local_set
local_set.add(mid(str2,j,i))
print mid(str2,j,i) + ' - FAIL, PASS'
else:
print mid(str2,j,i) + ' - FAIL, FAIL'
else:
print mid(str2,j,i) + ' - PASS'
#solution found?
best_option = ''
for option in local_set:
if len(option) < len(best_option) or best_option == '':
best_option = option
return best_option
本质上,我使用的逻辑是在 str1 中查找 str2 的子字符串,从可能的最大子字符串开始。当我发现一个不合适的,我将它添加到一个可能的解决方案集中。如果我发现另一个不适合 str1 的子字符串,我只会将它添加到可能的选项中,前提是它也是所有其他潜在选项的子字符串。因此,最后这个集合中最小的子字符串将包含第一个乱序字符。
所以,使用这个算法,我总是知道乱序部分从哪里开始。。但是,我不知道如何实际提取出乱序的部分。
我尝试将字符串反向传递给函数,这给了我从后面的字符串中第一个字符实例,然后在这里给了我完整的无序子字符串。但是,如果有多个部分乱序怎么办?此外,根据我的测试,该脚本仅返回 str2 中子字符串乱序的第一个实例。例如:
str1 = 'helloworld'
str2 = 'hworldello'
将返回 'hw',告诉我 'w' 是字符串乱序的地方。但在这个例子中,如果 'ello' 乱序而不是 'world' 子字符串,它会更有意义,因为它更大。
我已经盯着这个问题看了一天多,并决定是时候向其他意见开放,特别是因为我觉得必须有更好的方法。那么大家怎么看呢?有人有什么绝妙的主意吗?
【问题讨论】:
-
您可以阅读有关 Levenshtein 距离en.wikipedia.org/wiki/Levenshtein_distance
-
我认为您应该从“乱序”的正式定义开始。
-
@juanbits Levenshtein distance 在这里有用吗? OP 正在寻找乱序的字符块