【问题标题】:Intersection of k ordered lists pythonk个有序列表的交集python
【发布时间】:2020-12-07 02:22:27
【问题描述】:

我正在学习 python 并尝试使用 SvS 算法(小与小)相交 k 个集合(有序列表)。我的程序成功了,但我必须多次运行该函数,直到它到达交叉点。如果您能提示我做错了,我将不胜感激。

def SvS_BS(Set_list):
    Set_list = sorted(Set_list)
    candidato = Set_list[0]
    answer_set = []
    for S in Set_list:
        lS=0
        for S in Set_list:
            for e in candidato:
                b = BusquedaBinaria(S,0,len(S)-1,e)
                if b == -1:
                    candidato.remove(e)
                else: 
                    lS += b                
    return candidato

注意:BusquedaBinaria 是二分搜索(是一种从排序的项目列表中查找项目的有效算法。它通过重复将列表中可能包含该项目的部分分成两半来工作,直到您缩小了范围可能的位置只有一个):

   def BusquedaBinaria( lista, izq, der, x):
    if der >= izq:
        m = izq + ( der-izq ) // 2
        if lista[m] == x:
            return m
        if lista[m] > x:
            return BusquedaBinaria(lista, izq,m - 1, x)
        return BusquedaBinaria(lista, m + 1, der, x)
    return -1

如果我使用这些示例运行该函数:

A=[8, 316, 456, 802, 907, 1072, 1222, 1227, 1472, 1497, 1552, 1566, 1728, 2025, 2283, 2367, 2383, 2789, 3024, 3108, 3170, 3178, 3224, 3249, 3252]
B=[8, 1222, 10862, 18559, 28129, 41980, 43513, 44066]

第一个输出是:

SvS_BS([A,B])
output: [8, 907, 1222, 1552, 2283, 3024, 3224]

我再次运行该函数并得到:

output: [8, 1222, 3224] 

最后我再次运行它并得到输出(这是预期的结果)

output:[8, 1222]

提前谢谢你能帮我在第一次执行中得到结果

【问题讨论】:

  • 让您的问题自成一体。我们不知道BusquedaBinaria 是什么。
  • 你是对的,对不起。对应二分查找。我将在几秒钟内编辑问题

标签: python list set intersection set-intersection


【解决方案1】:

我在您的代码中发现了一些小错误。 首先,您在 Set_List 中对 S 进行两次迭代,只是为了重置 lS 值(您可以在 1 个循环内执行此操作),但无论如何您永远不会使用该变量。

此外,当您在 Set_List 中为 S 执行操作时,您无需在循环中检查候选列表 对自身。所以我改成

for S in range(1,len(Set_list)):

这只会在第一个(候选)之后迭代集合。 现在你在 S 中得到一个整数,所以我将你的二分搜索改为

b = BusquedaBinaria(Set_list[S],0,len(Set_list[S])-1,e)

现在这应该检查候选集与所有其他集除了本身。

最后,我认为这里最大的问题是设计和技术问题。第一个技术:您从候选对象中删除 当您对其进行迭代时,这是一个坏主意并且会使其跳过值。

因此,您希望将第一组与所有其他组进行比较,因此我将颠倒您的循环顺序,如下所示。但您还必须确保只返回 all 其他列表中的值。 (我认为您在未使用的 lS 变量中很接近这个想法)。由于您从未真正使用从二进制搜索返回的位置,因此我成功查找返回 1,并将其累积到 b 值中。如果该 b 值在搜索所有其他列表(减去候选)后添加到列表数量,那么它在所有列表中,我们将其添加到答案集中。然后我们返回答案集。

def BusquedaBinaria( lista, izq, der, x):
    if der >= izq:
        m = izq + ( der-izq ) // 2
        if lista[m] == x:
            return 1
        if lista[m] > x:
            return BusquedaBinaria(lista, izq,m - 1, x)
        return BusquedaBinaria(lista, m + 1, der, x)
    return -1
def SvS_BS_d(Set_list):
    Set_list = sorted(Set_list)
    comp_list_len = len(Set_list)-1
    candidato = Set_list[0]
    answer_set = []
    for e in candidato:
        b = 0
        for S in range(1, len(Set_list)):
            b += BusquedaBinaria(Set_list[S],0,len(Set_list[S])-1,e)
        if b == comp_list_len:
            answer_set.append(e)

    return answer_set

我认为这应该可行,我也尝试了一个额外的数组,但没有进行详尽的边缘案例测试,如果适合你,请告诉我!

【讨论】:

  • 在晨光中再看一遍,我只想提一下,对于相对较小长度的 Set_List,这应该可以正常工作。如果您打算拥有任意长的集合列表,或者只是想做一个小的优化,您可以检查 BusquedaBinaria 是否返回 -1,如果是,“继续”到候选中的下一个 e。 (在 if 检查中使用 continue 关键字)。删除 b==comp_list_len 检查并将其附加到 for 循环之后的答案集(即它从未达到“继续”条件。)直觉是检查没有列表 dont 有它,而不是所有列表做。
  • 德文塔克。非常感谢你。你真的帮了我很多。我会考虑你的意见。我正在学习 python,我对它们感到非常兴奋。再次感谢。
猜你喜欢
  • 1970-01-01
  • 2011-04-20
  • 1970-01-01
  • 1970-01-01
  • 2015-06-27
  • 2018-05-16
  • 2016-02-06
  • 1970-01-01
  • 2018-12-08
相关资源
最近更新 更多