在数字列表中找到第二大

时间:2013-11-01 00:09:34

标签: python arrays

我必须通过分而治之算法从列表中找到第二大数字和最大数字。问题是一切都是正确的,除了我使用像a和b这样的索引的部分。因为它工作得更快。价格便宜。不需要重写代码或发送其他代码和方法。请帮助我解决它,如果你可以..任何帮助任何想法欢迎。感谢

#!/usr/local/bin/python2.7

def two_max(arr,a,b):
      n = len(arr)
      if n==2: 
          if arr[0]<arr[1]: 
             return (arr[1], arr[0])
          else:
             return (arr[0], arr[1])

      (greatest_left, sec_greatest_left) = two_max(arr,a (a+b)/2)
      (greatest_right, sec_greatest_right) = two_max(arr,(a+b)/2,b)
      if greatest_left < greatest_right: 
          greatest = greatest_right
          if greatest_left < sec_greatest_left: 
              return (greatest, sec_greatest_left)
          else:
              return (greatest, greatest_left)
      else:
          greatest = greatest_left
          if greatest_right < sec_greatest_right: # Line 4
              return (greatest, sec_greatest_right)
          else:
              return (greatest, greatest_right) 

3 个答案:

答案 0 :(得分:1)

你为什么不这样做:

>>> def getIlargest(arr, i):
        if (i <= len(arr) and i > 0):
            return sorted(arr)[-i]

>>> a = [1,3,51,4,6,23,53,2,532,5,2,6,7,5,4]      
>>> getIlargest(a, 2)
53

我更进一步,测试了3种方法:

  1. 使用计数排序 - getIlargestVer2
  2. 使用python sorted函数 - getIlargestVer1
  3. 使用堆 - heapIlargest作为@abarnert建议。
  4. 结果:

    对于大小从1到大约5000 sorted的数组是最好的,对于较大的数组,heapq.nlargest用法是赢家:

    绘制大小介于[1*150, 55*150]

    之间的数组

    enter image description here

    *阵列之间的全扫描,大小为[1 * 150,300 * 150]:*

    enter image description here

    我使用的代码如下,3个方法实现在setup字符串:

    setup = """
    
    import heapq, random
    
    a = random.sample(xrange(1<<30), 150)
    a = a * factor
    
    class ILargestFunctions:
    
        # taken from [wiki][3] and was rewriting it.
        def counting_sort(self, array, maxval):
            m = maxval + 1
            count = {}
            for a in array:
                if count.get(a, None) is None:
                    count[a] = 1
                else:
                    count[a] += 1
            i = 0
            for key in count.keys():
                for c in range(count[key]):
                    array[i] = key
                    i += 1
            return array
    
        def getIlargestVer1(self, arr, i):
             if (i <= len(arr) and i > 0):
                  return sorted(arr)[-i]
    
        def getIlargestVer2(self, arr, i):
             if (i <= len(arr) and i > 0):
                  return self.counting_sort(arr, max(arr))[-i]
    
        def heapIlargest(self, arr, i):
            if (i <= len(arr) and i > 0):
                return heapq.nlargest(i,arr)
    
    n = ILargestFunctions() 
    
    """
    

    主线触发性能计数并绘制收集的数据:

    import timeit
    import numpy as np
    import matplotlib.pyplot as plt
    
    if __name__ == "__main__":
        results = {}
        r1 = []; r2 = []; r3 = [];
        x = np.arange(1,300,1)
        for i in xrange(1,300,1):
            print i
            factorStr = "factor = " + str(i) + ";"
            newSetupStr = factorStr + setup
            r1.append(timeit.timeit('n.getIlargestVer1(a, 100)', number=200, setup=newSetupStr))
            r2.append(timeit.timeit('n.getIlargestVer2(a, 100)', number=200, setup=newSetupStr))
            r3.append(timeit.timeit('n.heapIlargest(a, 100)', number=200, setup=newSetupStr))
            results[i] = (r1,r2,r3)
        p1 = plt.plot(x, r1, 'r', label = "getIlargestVer1")
        p2 = plt.plot(x, r2, 'b' , label = "getIlargestVer2")
        p3 = plt.plot(x, r3, 'g' , label = "heapIlargest")
        plt.legend(bbox_to_anchor=(1.05, 1), loc=1, borderaxespad=0.)
        plt.show()
    

答案 1 :(得分:1)

最大的问题是你永远不会接近你的递归基础案例。

基本案例是len(arr) == 2。但每当你打电话给自己时,你只需按原样arr传递:

  (greatest_left, sec_greatest_left) = two_max(arr,a,(a+b)/2)
  (greatest_right, sec_greatest_right) = two_max(arr,(a+b)/2,b)

(请注意,我猜测第一个中的逗号,因为当你发布它时,你实际上将数字a称为函数,这不太可能做任何有用的事情......)< / p>

因此,您的基本案例应考虑ab,如下所示:

if b-a == 2:
    if arr[a]<arr[a+1]:
        return (arr[a+1], arr[a])
    else:
        return (arr[a], arr[a+1])

...或者你应该发送一片arr而不是整件事 - 在这种情况下你首先不需要ab

  (greatest_left, sec_greatest_left) = two_max(arr[:len(a)/2])
  (greatest_right, sec_greatest_right) = two_max(arr[len(a)/2:])

任何一方都会解决你的第一个问题。当然,对于大多数输入,该功能仍然不工作。实际上,只有当列表的长度为2的幂时,它才有效。

如果这不是一个足够好的提示,如何解决它:如果b-a是3,会发生什么?显然你不能将它分成两半,两者的大小都是2或更大。因此,您需要为b-a == 1编写另一个基本案例,并返回某些,这将使算法的其余部分工作。

答案 2 :(得分:0)

@ 0x90有正确的想法,但他让它逆转了。

def find_i_largest_element(seq, i):
    if (i <= len(seq) and i > 0):
        s = sorted(seq, reverse=True)
        return s[i-1]

顺便问一下,这是一项家庭作业吗?如果是这样,你必须使用的算法背后的整个想法是什么?