【问题标题】:How to sum the two largests elements in a list?如何将列表中的两个最大元素相加?
【发布时间】:2018-07-17 21:35:54
【问题描述】:

我有一个这样的列表:

[1, 2, 5, 2, 7, 3, 9, 5...]

有没有一种有效的方法可以在这里找到两个最大元素的总和:

for i in range():
    for j in range():

我发现了这个: "最大子数组问题"

但我还没有完全理解它的作用。

【问题讨论】:

  • 所以在这种情况下,结果将是 9 + 7 ?
  • 您可以对数组进行排序,使最大的数字在开头,然后将前两个元素相加
  • 是的,但就我而言,我有一个随机列表。我把它作为输入,我尽量避免检查每个元素
  • @TrueBad0ur 你应该澄清一些非常重要的事情。当最大值发生不止一次时,所需的输出是什么?例如,如果您的列表是[1, 2, 5, 2, 7, 3, 9, 9],您想要的答案是9+9 还是9+7

标签: python algorithm list sub-array


【解决方案1】:
sum(sorted([9,8,1,3,4,5,7,0])[-2:])
  1. 对所有元素进行排序
  2. 获取最后两个元素
  3. 总结一下

【讨论】:

  • sum(sorted([9,8,1,3,4,5,7,0], reverse=True)[0:2])
  • 应该有一个O(N) 解决方案
  • 或者我们可以使用sum(heapq.nlargest(2, your_list))
  • 这是一个线性问题的 n log n 解;不应该被接受。其他人已经给出了线性时间解决方案:读取一次数组,跟踪两个最大的 elt,并将它们添加到末尾。
  • @Dave 这取决于...就纯性能而言,您是对的,这是次优的。但是,您知道,如果您没有数百万个数字,那么该解决方案与线性解决方案在性能方面的差异将只有几微秒。然而,的不同之处在于这段代码更具可读性。
【解决方案2】:

这是一个线性时间解:

#initialize these to huge negative numbers
largest = -1e10
second_largest = -1e11
l = [9,8,1,3,4,5,7,0]
for item in l:
    if item > largest:
        second_largest = largest
        largest = item
    elif item > second_largest:
        second_largest = item

print(largest+second_largest)
# 17

【讨论】:

    【解决方案3】:

    这里是线性解:

    x = [1, 2, 5, 2, 7, 3, 9, 5]
    max1 = -1;
    max2 = -1;
    for i in range(len(x)):
        if x[i] > max1:
            max2 = max1
            max1 = x[i]
        elif x[i] > max2:
            max2 = x[i]
    
    print(max1+max2)
    

    如果您的数组仅包含正整数,则考虑将 max1、max2 更改为可能的最低值

    【讨论】:

      【解决方案4】:

      另一个 O(n) 解决方案,但更 Pythonic,放弃了一点性能(在列表上迭代 4 次)

      l = [1, 2, 5, 2, 7, 3, 9, 5]
      
      # find largest
      largest = max(l)
      # remove from list
      l.remove(largest)
      # second largest
      largest2 = max(l)
      # remove from list
      l.remove(largest2)
      print(largest+largest2)
      >> 16
      

      为了让它更紧凑一点,一行中完全相同的过程:

      l = [1, 2, 5, 2, 7, 3, 9, 5]
      l.pop(l.index(max(l))) + l.pop(l.index(max(l)))
      print(largest+largest2)
      >> 16
      

      【讨论】:

      • 你不需要l.remove(largest2),但这行得通。
      • 我喜欢这个解决方案。简单高效。如果你不允许使用内置的 max() 和 remove(),你可以对它们进行编码,但我喜欢这个想法的简单性。
      • 此解决方案可能有效或无效,具体取决于您对“最大”的定义。如果最大的数字重复会发生什么?你应该删除它的所有实例,这是另一个 \$O(n)\$ 操作,还是给出largest * 2 作为结果?
      • 并非如此,remove 会删除最大值的第一个匹配项。下一步将找到相同的最大值(不同的索引)并将其删除。如此快速的答案是它将具有与其他解决方案相同的行为(例如排序,获取 [:2])。它将导致最大 * 2
      【解决方案5】:

      如果你不介意使用库,可以使用heapqnlargest

      import heapq
      x = [1, 2, 5, 2, 7, 3, 9, 5]
      

      然后

      sum(heapq.nlargest(2, x))
      

      会回来

      16
      

      pandas 也是一个选项(但只有在您导入它时才使用它,因为它是一个相当重的依赖项):

      import pandas as pd
      pd.Series(x).nlargest(2).sum()
      

      也返回16

      如果您有重复的最大值,您可以使用sets

      x = [1, 2, 5, 2, 7, 3, 9, 5, 9]
      

      然后

      sum(heapq.nlargest(2, x))
      

      会回来

      18
      

      作为9 + 9 = 18

      sum(heapq.nlargest(2, set(x)))
      

      将返回

      16
      

      然后计算9 + 7 = 16

      【讨论】:

        【解决方案6】:

        具有唯一编号

        这是最简单的方法

        a = [1, 2, 5, 2, 7, 3, 9, 5]
        m1 = max(a)
        a.pop(a.index(m1))
        m2 = max(a)
        print(m1 + m2)
        

        输出:16

        如果你有更多相等的数字,但你想摆脱它们 - 这样你就可以添加两个最大的不同数字 - 你可以这样做:

        a = [1, 2, 5, 2, 7, 3, 9, 5]
        a = set(a)
        m1 = max(a)
        a = list(a)
        a.pop(a.index(m1))
        m2 = max(a)
        print(m1 + m2)
        

        输出:16

        如果您想在列表中添加最大的数字,即使它们相同(即 9 和 9),请使用第一个代码示例,它会为您工作。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2016-12-12
          • 2021-09-11
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-03-05
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多