【问题标题】:Best way to select random array element avoiding exclusion list选择随机数组元素避免排除列表的最佳方法
【发布时间】:2020-08-19 18:02:58
【问题描述】:

在不包括一组位置的 n*n 矩阵中选择随机位置的最优雅/有效的方法是什么?

示例:想象一个棋盘,所以 n=8,总共有 8*8 = 64 个位置。在 (0, 0), (5, 3), (7, 4) 位置有 3 个棋子。任务是选择一个尚未被棋子占据的随机位置。

这是我想出的:

def get_random_position(n, occupied_positions):
    while True:
        random_position = (random.choice(range(n)), random.choice(range(n)))
        if random_position not in occupied_positions:
            return random_position
    
    
if __name__ == '__main__':
    unoccupied_random_position = get_random_position(8, [(0, 0), (5, 3), (7, 4)])
    print(unoccupied_random_position)

时间复杂度对于 n 是恒定的,并且与占用单元的数量成线性关系。因此,如果 90% 的单元格已被占用,则循环将迭代更长的时间。

有没有更好的方法?

【问题讨论】:

    标签: algorithm


    【解决方案1】:

    首先,很明显你不能比 O(m) 的最坏情况做得更好,其中 m 是矩阵中的单元数,即 m=n²,其中 n 是矩阵的宽度:在最坏的情况下,除一个以外的所有单元格都被占用,您至少需要查看每个单元格 m-1 个坐标。

    我还应该在这里提到,在您的代码中random_position not in occupied_positions 不是一个常量操作。每次迭代该列表以找到匹配项。

    这里有一个替代方案:

    您可以导出空闲单元格的数量,生成一个达到该限制的随机数,然后迭代占用的单​​元格以适应该数字(增量)以指向实际空闲的单元格。在这个过程中,数字唯一地映射到 x 和 y 坐标。

    为了高效,我们必须假设占用的单元格列表已经排序。

    这是如何编码的:

    def get_random_position(n, occupied_positions):
        rnd = random.randint(0, n*n - 1 - len(occupied_positions))
        for (row, col) in occupied_positions:
            if rnd < row*n+col:
                break
            rnd += 1
        return (rnd // n, rnd % n)
    

    这段代码在O(k) 中运行,其中koccupied_positions 列表的大小。如果我们不能保证这个列表是有序的,那么我们需要先对它进行排序,这样就决定了整体的时间复杂度,即O(klogk)

    【讨论】:

    • 有趣的方法,我确实考虑过扁平化数组但没有考虑这种方法,谢谢
    【解决方案2】:

    与其选择随机位置并检查它是否被占用,不如先扫描板以查看哪些位置是空缺的。创建这些地点的列表。这是O(n),其中 n 是总板空间的数量。然后,从 only 开放点中选择一个随机元素。请注意,当您只有几个空位时,随机选择仍然只从几个空格中选择,并且您只需要随机抽样一次。

    【讨论】:

    • 扫描板以查看哪些职位空缺不会是 O(n),因为每个职位都必须检查整个已占用职位列表,不是吗?
    猜你喜欢
    • 2021-12-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多