重新排序列表,保持重复元素之间的最大距离

问题描述 投票:0回答:0

给定一个列表,即: [1,1,2,2,3,5]

我想重新订购: [1,2,3,5,1,2]

我可以使用什么算法?

按逻辑进行: 我正在考虑计算发生次数,比方说,即: [1, 1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 44, 4, 5, 6, 1, 4, 5, 3, 6, 7, 8, 9, 11, 123 , 22, 44, 1, 5, 5]

将给出这个“出现次数”矩阵 2x30: [(3, 10), (1, 4), (5, 4), (44, 2), (4, 2), (6, 2), (7, 1), (8, 1), ( 9, 1), (11, 1), (123, 1), (22, 1)]

所以我会:

  • 计算所有重复次数超过 1 次的数字,在本例中为 6 个数字
  • 有 3 个数字出现 2 次:
    • 6,它将进入位置 3 (0+5-2) 和 24 (29-5)
    • 4,将位于位置 4 (0+5-1) 和 25 (29-5+1)
    • 44号将进入位置5(0+5)和26(29-5+2)
  • 有 2 个数字出现 4 次
    • 5 将位于位置 1 (0+6-3-1) 和 27 (29-6+3) 之间,每大约 6 个数字
    • 1 将位于位置 2 (0+6-3) 和 28 (29-6+3+1) 之间,每大约 6 个数字
  • 有 1 个数字出现 10 次
    • 3 将位于位置 0 和 29 之间,每大约 3 个数字。

等等。 然后用不重复的数字填满空的位置。 当发生碰撞时(位置已被占据)交替+1、-1、+2、-2等直到找到空闲位置 我想出了这段代码,大胆地遵循我的算法,

from collections import defaultdict

def find_nearest_none(arr, position):
    if arr[position] is None:
        return position

    step = 1
    while True:
        left_pos = position - step
        right_pos = position + step

        if left_pos >= 0 and arr[left_pos] is None:
            return left_pos
        elif right_pos < len(arr) and arr[right_pos] is None:
            return right_pos
        elif left_pos < 0 and right_pos >= len(arr):
            # Both left and right positions are out of bounds
            return False

        step += 1

def max_distance_list(nums):
    num_occurrences = {}
    t = len(nums)
    out = [None] * t
    
    for num in nums:
        num_occurrences[num] = num_occurrences.get(num, 0) + 1
    num_occurrences = sorted(num_occurrences.items(), key=lambda item: item[1], reverse=True)

    grouped_data = defaultdict(list)
    for key, value in num_occurrences:
        grouped_data[value].append(key)

    print(grouped_data)

    start_pos = 0 
    for x, y in dict(grouped_data).items():
        print("Start pos:", start_pos)
        for z in y:
            sep = t // x
            pos = start_pos;
            for i in range(x):
                free_pos = find_nearest_none(out, pos)
                out[free_pos] = z 
                pos+=sep;
            start_pos+=1;
    return out

输出:[3, 1, 5, 3, 44, 4, 3, 6, 1, 3, 5, 7, 3, 8, 1, 3, 5, 44, 3, 4, 6, 3, 1, 5, 3, 9, 11, 3, 123, 22]

但这不是一个最佳结果,只是可以接受,而且离快速还很遥远。 是否有一些“已经完成”的功能可以更好更快地做到这一点?

如果没有,我将分批进行,并将使用这个“可接受”的结果,因为 它用于创建一个爬虫队列,以隔离对相同 IP 和/或域的调用

感谢任何帮助

python list logic
© www.soinside.com 2019 - 2024. All rights reserved.