简体   繁体   English

计算列表中的循环移位对

[英]Calculate circular shift pairs in a list

A circular shift moves some of the digits in a number to the beginning of the number, and shifts all other digits forward to the next position. For example, all of the circular shifts of 564 are 564, 645, 456 .循环移位将数字中的一些数字移动到数字的开头,并将所有其他数字向前移动到下一个 position。例如,564 的所有循环移位都是564 564, 645, 456

Lets say two numbers of equal length a and b are circular pairs if a can become b via circular shifting.假设两个长度相等的数字ab循环对,如果a可以通过循环移位变成b Using the example above, the circular pairs of 564 are 645 and 456 .使用上面的示例,循环对564645456

Given an array of positive integers nums , count the number of circular pairs i and j where 0 <= i < j < len(nums)给定一个正整数数组nums ,计算循环对ij的数量,其中0 <= i < j < len(nums)

For example, circular_shifts([13, 5604, 31, 2, 13, 4560, 546, 654, 456]) should return 5 .例如, circular_shifts([13, 5604, 31, 2, 13, 4560, 546, 654, 456])应该返回5 With the pairs being (13, 31), (13, 13), (5604, 4560), (31, 13), (546, 654) .对是(13, 31), (13, 13), (5604, 4560), (31, 13), (546, 654)

I wrote a brute force solution that saves all circular shifts of a number in a dictionary shifts and for every number num in nums , I check all the following numbers and if a number num2 the same digits as num , I see if num2 is in num 's circular shifts.我写了一个蛮力解决方案,将数字的所有循环移位保存在字典shifts中,对于nums中的每个数字num ,我检查以下所有数字,如果数字num2num的数字相同,我看看num2是否在num中的循环移位。 If it is then I added this to the total count.如果是,那么我将其添加到总数中。

Unfortunately this algorithm runs too slowly and times out, I'm looking for a faster way to solve this problem can anyone think of optimizations, clever tricks, or other strategies to speed this up?不幸的是,这个算法运行得太慢而且会超时,我正在寻找一种更快的方法来解决这个问题,有人能想到优化、巧妙的技巧或其他加速这个问题的策略吗?

  1. Replace every number in the array with its greatest cyclic shift.用最大循环移位替换数组中的每个数字。 1234, for example, would become 4123例如,1234 将变为 4123
  2. Count the occurrences of each resulting number计算每个结果数字的出现次数
  3. If a number occurs n times, that represents n(n-1)/2 cyclic shift pairs.如果一个数字出现 n 次,则表示 n(n-1)/2 个循环移位对。 Add them all up.把它们都加起来。

Not very elegant as not much time but the following should be faster as does not repeatedly access the list.由于时间不多,不是很优雅,但是由于不重复访问列表,因此以下应该会更快。 Shifting is done on string for simplicity.为简单起见,移位是在字符串上完成的。

from collections import Counter

def big(num):
    max = num
    s = str(num)
    for _ in s:
        x = int(s[-1] + s[0:-1])
        if x > max:
            max = x
    return max
        
circs = [big(z) for z in mylist]

c = Counter(circs)

total = 0
for i in c:
    if c[i] > 1:
        total += c[i]
print(total)

Here's my solution, where we这是我的解决方案,我们

  1. iterate through the list遍历列表
  2. rotate each number length-1 times将每个数字旋转 length-1 次
  3. and print only if the number is found in the remaining list并且仅当在剩余列表中找到该数字时才打印
    numbers = [13, 5604, 31, 2, 13, 4560, 546, 654, 456]
    # shift_pairs = [(13,31),(13,13),(5604,4560),(31,13),(546,654)]
    pairsFound = 0
    for i in range(len(numbers)):
        number = numbers[i]
        length = len(str(number))
        numberToRotate = number
        shift_remaining = length - 1
        temp_list = numbers[i+1:]
        while(shift_remaining >= 0):
            t_remainder = numberToRotate % 10 # 4
            numberToRotate = numberToRotate // 10 # 560
            numberToRotate = numberToRotate + t_remainder * 10 **(length-1) # 4560
            # we should also check for length for cases like 4560, where on a shift we get 456
            if(numberToRotate in temp_list and len(str(numberToRotate)) == length):
                print("({},{})".format(number,numberToRotate))
                pairsFound += 1
            shift_remaining -= 1
    print("no of pairs:", pairsFound)

output output

(13,31)
(13,13)
(5604,4560)
(31,13)
(546,654)
no of pairs: 5

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM