Group Shifted Strings
要点:开始就想到了string之间前后字符diff要相同。
- 思维混乱的地方:和某个string的diff之间是没有关系的。所以和单个string是否在那个点会出现z->a也没关系。
- 唯一tricky的地方是z->a的diff为-25,其和1是等价的。同理a->z diff为25,其和-1是等价的。显然差值是+/-26,两个值map到一个value的方法是(x+26)%26,+26是为了变到positive,%26是26循环。实际上可以用26 + val if val < 0 else val
错误点:
- 因为单个字符的范围是0-25,所以encoding要加delimiter
- python的get(key, default)得到的是临时object,而不会put internal value,要用collections.defaultdict()
- int() vs ord()
# Given a string, we can "shift" each of its letter to its successive letter, for example: "abc" -> "bcd". We can keep "shifting" which forms the sequence:
# "abc" -> "bcd" -> ... -> "xyz"
# Given a list of strings which contains only lowercase alphabets, group all strings that belong to the same shifting sequence.
# For example, given: ["abc", "bcd", "acef", "xyz", "az", "ba", "a", "z"],
# A solution is:
# [
# ["abc","bcd","xyz"],
# ["az","ba"],
# ["acef"],
# ["a","z"]
# ]
# Hide Company Tags Google Uber
# Hide Tags Hash Table String
# Hide Similar Problems (M) Group Anagrams
from collections import defaultdict
class Solution(object):
def groupStrings(self, strings):
"""
:type strings: List[str]
:rtype: List[List[str]]
"""
def getDiff(s):
diff = []
for pair in zip(s, s[1:]):
u, v = pair[0], pair[1]
# print u,v
val = ord(v)-ord(u)
diff.append(str(val+26 if val<0 else val))
return '$'.join(diff)
groups = defaultdict(list)
single = []
for s in strings:
if len(s)==1:
single.append(s)
else:
groups[getDiff(s)].append(s)
ret = groups.values()
if single:
ret.append(single)
return ret
sol = Solution()
assert sol.groupStrings(["abc", "bcd", "acef", "xyz", "az", "ba", "a", "z"])==[['az', 'ba'], ['acef'], ['abc', 'bcd', 'xyz'], ['a', 'z']]