我提出的解决方案是首先尝试“链接”尽可能多的对以形成可以互换的索引集 - 例如在您的第一个示例中,[[1, 4], [3, 4]]
可以变为[[1, 3, 4]]
. 然后可以按字典顺序对这些索引子集中的每一个进行排序以形成输出。实现是这样的:
def build_permitted_subs(pairs):
perm = []
for a, b in pairs:
merged = False
for ind, sub_perm in enumerate(perm):
if a in sub_perm or b in sub_perm:
sub_perm.add(a)
sub_perm.add(b)
merged = True
break
else:
perm.append(set([a, b]))
if merged:
for merge_perm_ind in reversed(range(ind + 1, len(perm))):
if perm[merge_perm_ind] & sub_perm:
sub_perm.update(perm[merge_perm_ind])
perm.pop(merge_perm_ind)
return list(map(sorted, perm))
def swap_lex_order(swap_str, _pairs):
pairs = [[a - 1, b - 1] for a, b in _pairs]
out = list(swap_str)
perm = build_permitted_subs(pairs)
for sub_perm in perm:
sorted_subset = sorted(sub_perm, key=lambda ind: swap_str[ind], reverse=True)
for sort, targ in zip(sorted_subset, sub_perm):
out[targ] = swap_str[sort]
return "".join(out)
print(swap_lex_order("dznsxamwoj", [[1, 2], [3, 4], [6, 5], [8, 10]]))
print(swap_lex_order("abdc", [[1, 4], [3, 4]]))
print(swap_lex_order("acxrabdz",[[1,3], [6,8], [3,8], [2,7]]))
输出:
zdsnxamwoj
dbca
zdxrabca
我还重命名了你的参数 not to use str
,这已经是一个非常基本的 Python 内置函数。请注意,我的代码可能不像 Pythonic 一样,但我认为它可以很好地说明算法,并且它不会受到任何主要的性能影响。我怀疑这种方法的复杂性相当低——它通常是“智能的”,因为它不会暴力破解任何东西,并且使用O(n log n)
排序。第一个例子似乎是正确的。请注意,这会将每对转换为从 0 开始的,因为这对于 Python 来说更容易。
这有点依赖于能够从相邻的排列(交换对)中形成任何排列(对链接的对进行排序)。这可能并不完全直观,但它可能有助于意识到您可以仅使用列表中的相邻交换来有效地执行插入(通过不断地在方向上交换元素)。使用相邻交换排列列表的一个示例是冒泡排序,您可能会意识到,如果任何排列都可以被冒泡排序,这意味着所有排列都可以通过冒泡排序达到。
如果您有任何问题,或者有任何问题,请告诉我,我将开始详细说明/调试。(截至格林威治标准时间 19:28,我已经注意到一个错误并将其编辑掉:)。错误 #2(在测试用例 3 中有重复的 z)也应该被修复。
关于错误 #1 的更多信息:
我没有对 . 返回的索引进行排序build_permitted_subs
,因此无法参考swap_str
.
有关错误 #2 的更多信息:
该build_permitted_subs
功能无法正常工作 - 具体来说,如果遇到可以分成两组的配对,这意味着这些组也应该加入在一起,这没有发生,现在会有两个不应该分开的组。这会导致 z 重复,因为两组都可以从 z 中提取。我草率地用一个标志和一个追溯 for 循环修复了这个问题。