Code signal: cyclic shift pairs

3,472 阅读1分钟

定义两数 a b 如果 a 的最后一位移到第一位一直移移到后面能形成b, 那么 a 是 b cyclic shift.
给定一个数组A, 如果A[i]是A[j]的cyclic shift并且 i < j那么 A[i] A[j]就是 cyclic shift pair.求这个数组一共有多少个cyclic shift pair. (456 的所有 cyclic shift 是:645, 564)


解法一: 暴力 O(n2)O(n^2)
遍历所有的对, 判断这一对数是不是cyclic shift, 如果是就res++, 如果不是就continue 但是会超时

解法二: 线性查找 O(n)O(n)
如果我们遇到了一个数, 我们可以把这个数存到map, 前提是map里所有的数都不是这个数的cyclic shift. map的key是这个数的str然后 value是这个数和这个数的cyclic shift出现的次数。同时把更新后的value累加到res里。 例如 [13, 5604, 31, 2, 13, 4560]
我们遇到 13, 把13放进字典. {13:1} res = 0
遇到5604, 没有5604的shift在字典里, 更新map. {13:1, 5604:1} res = 0
遇到31, 发现13是31 shift, 更新map. {13:1+1,5604:1} res = 0+1 = 1
遇到2, 没有发现shift, 更新map {13:2,5604:1,2:1} res = 1
遇到13, 发现shift, 更新map {13:2+1, 5604:1,2:1} res = 1+2 = 3
遇到4560, 发现shift, 更新map, {13:3, 5604:1+1, 2:1} res = 3+1 = 4

因为这题每个数取值在 [0,109][0, 10^9], 所以每次发现shift时间是常数, 遍历n次总共需要 O(n)O(n)时间

python代码:

def sol(a): 
    res = [0]
    dic = {}
    def check(s):
        s = str(s)
        for i in range(len(s)):
            s = s[-1]+s[:-1]
            if s in dic:
                res[0]+=dic[s]
                dic[s] +=1
                return
        dic[s] = 1
        return
    for n in a:
        check(n)
    return res[0]