【问题标题】:Python algorithm to compare two sorted lists and count how many elements are the samePython算法比较两个排序列表并计算有多少元素相同
【发布时间】:2018-05-08 02:08:07
【问题描述】:

我必须设计一个算法来比较两个相同长度的排序列表并返回它们之间的公共值的数量。

所以如果我有两个列表 a = [2, 9, 15, 27, 36, 40] 和 b = [9, 11, 15, 23, 36, 44],算法应该返回 3 的值两个列表中都有 9、15 和 36。

我知道使用集合可能会更容易,但由于我正在尝试学习数据结构和算法,所以我更愿意学习更长的时间(更难的方式)。

我当前的代码使用了目前不起作用的任何数组合并算法,因为我仍然对 r1 和 r2 感到困惑,尽管我认为它们将是数组中最正确的元素,但我不知道如何得到它。例如。 r1 = 40(来自列表 a)和 r2 = 44(来自列表 b)?

global a
a = [2, 9, 15, 27, 36, 40]

global b
b = [9, 11, 15, 23, 36, 44]

global c
c = []

def merge (a1, a, r1, a2, b, r2, c, list3):
    i = a
    j = b
    k = c
    r1 = 
    r2 = 
    while i <= r1 and j <= r2:
        if a1[i]<=a2[j]:
            a3[k] = a1[i]
            i += 1
        elif a3[k] >= a2[j]:
            j += 1
            k += 1
    while i <= r1:  
        a3[k] = a1[i]
        i += 1
        k += 1 
    while j <= r2:  
        a3[k] = a2[j]
        j += 1
        k += 1  

感谢您的帮助和反馈。

【问题讨论】:

  • 一个简单的解决方案应该在 O(NlogN) 时间内是可行的。您在寻找什么样的解决方案?
  • @cᴏʟᴅsᴘᴇᴇᴅ 因为我正在使用合并排序算法,就时间复杂度而言,O(n log(n)) 不是最好的吗?如果不是,你会推荐什么?如果我错了,请原谅我还在学习这些东西。
  • 既然列表已经排序了,为什么还要运行mergesort呢?我在想什么:如果您的列表不包含重复项,您可以遍历列表 1 并在列表 2 上进行二进制搜索。
  • 由于这是一些家庭作业的一部分,讲师说要制定一个算法来执行图块建议的操作。他希望我们使用数组合并算法来比较两个列表并修改它以增加一个计数,如果有共同的值。
  • merge() 只是O(n) - 你不需要merge_sort()。计算重复也只是O(n)

标签: python python-3.x algorithm array-merge


【解决方案1】:

好的,如果我正确阅读了您的问题,您希望在两个等长的排序列表中找到共同元素并返回共同元素的数量。我对这里使用合并有点困惑。

无论如何,如果这是您希望算法执行的操作。由于它已经排序,我们可以简单地遍历两个列表并在线性时间内找到公共元素。

算法:

  • ij分别为a1a2的索引,分别初始化为0
  • 如果a1[i] &lt; a2[j] 我们知道a1[i]a2 中不存在,因为ij 指向各自数组中的最小元素。所以我们向前移动i
  • a2[j] &lt; a1[i]相同。
  • 如果 a1[i] == a2[j] 则我们找到了一个公共元素,我们将 ij 都提前 1 并继续直到数组的末尾。

代码

def find_common(a1, a2):
    list_len = len(a1)
    a3 = []
    i = j = 0
    while i < list_len and j < list_len:
        if a1[i] < a2[j]:
            i += 1
        elif a2[j] < a1[i]:
            j += 1
        else:
            a3.append(a1[i])    
            i +=1
            j +=1
    return a3

a = [2, 9, 15, 27, 36, 40]
b = [9, 11, 15, 23, 36, 44]
print(find_common(a, b))

【讨论】:

  • 谢谢,这很好用,只需添加print(len(find_common(a, b))) 即可获得它们之间的共同值的数量。
  • 如果您只需要只有一个计数器的号码而不是列表a3。例如c = 0 并将 a3.append(a1[i]) 替换为 c += 1 然后 find_common() 将返回 3
  • @AChampion 是的,你是对的。我添加了它,这样它会更清楚一点。
【解决方案2】:

使用哈希表可以在线性时间内解决这个问题。

您可以使用 python 字典将一个列表存储在哈希表中,其中键是元素(在本例中为整数),值是元素出现的次数。运行时间:O(n)

然后遍历另一个列表并对每个元素进行哈希表查找。保留一个变量来计算常见值。运行时间:O(n)。

为避免重复计算,在迭代时检查前一个元素是否相同,在这种情况下移动到下一个元素。您将需要一个额外的变量来跟踪前一个元素。

【讨论】:

    【解决方案3】:

    r1r2 只是两个列表的长度。
    对 2 个列表进行简单合并并不像您的示例那么复杂,这是一个简化的合并:

    def merge(a1, a2):
        r1, r2 = len(a1), len(a2)
        a3 = []
        i = j = 0
    
        while i < r1 and j < r2:
            if a1[i] < a2[j]:
                a3.append(a1[i])
                i += 1
            else:
                a3.append(a2[j])
                j += 1
    
        while i < r1:
            a3.append(a1[i])
            i += 1
        while j < r2:
            a3.append(a2[j])
            j += 1
    
        return a3
    
    In []:
    a = [2, 9, 15, 27, 36, 40]
    b = [9, 11, 15, 23, 36, 44]
    merge(a, b)
    
    Out[]:
    [2, 9, 9, 11, 15, 15, 23, 27, 36, 36, 40, 44]
    

    进行重复计数比这更简单,因为您不需要构建新列表,但这应该为您提供进行计数的基础,并且只有 O(n)

    【讨论】:

    • 不应该 a3.append(a2[i])a3.append(a2[j])
    • 是的,确实 - 已修复
    猜你喜欢
    • 2022-11-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多