题目:从给定字符串中随机出的三字符列表的集合中,恢复原始字符串,并且三字符列表按字符在字符串中出现顺序排列。作为简化,假设秘密字符串中不会有重复字母。如下:
secret = "whatisup"
triplets = [
['t', 'u', 'p'],
['w', 'h', 'i'],
['t', 's', 'u'],
['a', 't', 's'],
['h', 'a', 'p'],
['t', 'i', 's'],
['w', 'h', 's']
]
我想了许久,有这么一个思路:
- 分别提取集合triplets中列表第一、第二和第三项组成集合。
- 字符串中第一个字母只会在第一集合中出现,排除得出第一个字母。
- 从原始集合triplets中去掉找出的第一个字母,并在除去字母的该行末尾添加0,以保持三元素列表。
- 重复上述动作,直到triplets变成只包含0。
按上述思路,确实能够写出答案,但结果无比丑陋:
def recoverSecret(triplets):
res = []
while triplets:
t = list(zip(*triplets))
big = list(set(t[0]) - set(t[1] + t[2]))
if not big:
break
res.extend(big)
for item in triplets:
if big[0] == item[0]:
item.pop(0)
item.append(0)
return ''.join(res)
感觉要瞎了。看了下大神的代码,思路是这样的:
- 根据triplets生成原字符串的字符列表t,无重复,但非按顺序。
- 循环遍历triplets,每次循环按三字符列表中的顺序调整上一步的t中字符顺序。
结果如下:
def recoverSecret(triplets):
r = list({i for t in triplets for i in t})
for t in triplets:
fix(r, t[1], t[2])
fix(r, t[0], t[1])
return ''.join(r)
def fix(t, a, b):
if t.index(a) > t.index(b):
t.remove(a)
t.insert(t.index(b), a)
但上面的算法有问题,比如下面这个例子:
triplets = [
['w', 'h', 'p'],
['t', 'u', 'p'],
['w', 'h', 't'],
['t', 's', 'u'],
['a', 't', 's'],
['h', 'a', 'p'],
['t', 'i', 's']
]
当我确定了w, h两个的位置后,又要确认h, a的位置,此时a在h前面,所以把h的位置前提,但因为初始a在w前面,那h就位置放错了,后面又不再有w, h的位置调整,最后的结果当然是错的。
当然,解决方式也很简单,多循环一遍triplets:
for t in triplets * 2
以我的智商暂时就只能想到这里,如有更好的方法,请不吝赐教。