【问题标题】:Getting the indices of the X largest numbers in a list获取列表中 X 个最大数字的索引
【发布时间】:2012-05-12 02:37:07
【问题描述】:

除了 len() 或 range() 之外,请不要使用内置函数。我正在准备期末考试。

这是我的意思的一个例子。

def find_numbers(x, lst):


lst = [3, 8, 1, 2, 0, 4, 8, 5]

find_numbers(3, lst) # this should return -> (1, 6, 7)

我没有完全尝试过这个......无法找出最好的方法:

def find_K_highest(lst, k):
 newlst = [0] * k
 maxvalue = lst[0]


 for i in range(len(lst)):
    if lst[i] > maxvalue:
        maxvalue = lst[i]
        newlst[0] = i

【问题讨论】:

  • 当我尝试的时候没有太多尝试......无法真正弄清楚
  • 您只需要回答lenrange
  • @akaRem 这些是允许在考试中使用的唯一内置插件。
  • @Omerta:如果你把它分解成几个步骤,用伪代码执行算法,应该不会那么难。想想你(手动)如何找到列表中最高的 3 个项目。
  • 呃,我讨厌老师使用这些限制。我从标准库中获得了重新实现的功能,使思考简单任务变得更容易,但这种事情只是懒惰,而且会教坏做法。

标签: python algorithm


【解决方案1】:

从列表中取出前 3 (x) 个数字。最大值的最小值是这些。在您的情况下:3、8、1。它们的索引是(0、1、2)。构建它们的对((3,0),(8,1),(1,2))。

现在按最大值的大小对它们进行排序:((8,1), (3,0), (1,2))。

使用这个初始列表,您可以递归地遍历列表的其余部分。将最小值 (1, _) 与列表中的下一个元素 (2, 3) 进行比较。如果它更大(它是),将其排序到列表((8,1),(3,0),(2,3))中并丢弃最小的。

一开始你在前 3 名中有很多变化,但后来,它们变得很少。当然,在遍历时,您也必须保留有关最后位置(3、4、5,...)的 book。

前 N 个元素的插入排序应该非常高效。

Here is a similar problem in Scala 但不需要报告索引。

【讨论】:

    【解决方案2】:

    我不知道发布解决方案是否好,但这似乎有效:

    def find_K_highest(lst, k):
        # escape index error
        if k>len(lst):
            k=len(lst)
        # the output array
        idxs = [None]*k
        to_watch = range(len(lst))
        # do it k times
        for i in range(k):
            # guess that max value is at least at idx '0' of to_watch
            to_del=0
            idx = to_watch[to_del]
            max_val = lst[idx]
            # search through the list for bigger value and its index
            for jj in range(len(to_watch)):
                j=to_watch[jj]
                val = lst[j]
                # check that its bigger that previously finded max
                if val > max_val:
                    idx = j
                    max_val = val
                    to_del=jj
                # append it
            idxs[i] = idx
            del to_watch[to_del]
            # return answer
        return idxs
    

    PS 我试着解释每一行代码。

    【讨论】:

    • 这也使用了一堆列表方法...popappend__contains__ 仅举几例(我假设 __getitem__ 没问题——你真的可以没有那个就什么都不做)。
    • 我认为这里仍然存在索引问题。问题是j是to_watch中的一个项目,其最大的项目是len(lst)。所以,j 可以和len(lst) 一样大。 idx 被分配了j 的值,然后从to_watch 中删除该元素。如果 j (因此 idx 等于 len(lst) 并且您已经删除了某些内容,那么您的索引将超出范围。此外,我不清楚您是否真的要删除您想要的索引首先删除...
    • @akaRem -- 是的,我打错了。最大的项目是len(lst)-1。但是,您可能在del 语句中使用的最大索引是len(lst)-1,所以我的观点仍然相同。只需在 OP 提供的输入上尝试您的功能,您就会看到(我得到一个索引越界错误)。
    • @mgilson 该算法不适用于[9,1,2,3,4,5,6]。答案是[0, 0, 0] - 这是不对的。猜猜为什么!
    • 我已经更正了。现在完美运行!甚至改进了功能。
    【解决方案3】:

    你可以使用列表方法吗? (例如appendsortindex?)。如果是这样,这应该可行(我认为...)

    def find_numbers(n,lst):
        ll=lst[:]
        ll.sort()
        biggest=ll[-n:]
        idx=[lst.index(i) for i in biggest] #This has the indices already, but we could have trouble if one of the numbers appeared twice
        idx.sort()
        #check for duplicates.  Duplicates will always be next to each other since we sorted.
        for i in range(1,len(idx)):
           if(idx[i-1]==idx[i]):
             idx[i]=idx[i]+lst[idx[i]+1:].index(lst[idx[i]]) #found a duplicate, chop up the input list and find the new index of that number
             idx.sort()
        return idx
    
    lst = [3, 8, 1, 2, 0, 4, 8, 5]
    
    print find_numbers(3, lst)
    

    【讨论】:

    • 不允许列出方法,切片也不允许,即使在考试中也是如此。老师对这些东西很疯狂。
    • @jamylak...这是第一学期的计算机科学课...所有教授关心的是学习算法。教授不关心语法或内置函数。如果由教授决定,课程将用 C 语言授课。
    【解决方案4】:

    老兄。你有两种方法可以解决这个问题。

    第一种方法是聪明。把你的老师赶出去。她正在寻找的是递归。您可以在没有递归和没有内置函数或方法的情况下编写此代码:

    #!/usr/bin/python
    
    lst = [3, 8, 1, 2, 0, 4, 8, 5]
    
    minval=-2**64
    
    largest=[]
    
    def enum(lst): 
        for i in range(len(lst)): 
            yield i,lst[i]
    
    for x in range(3):
        m=minval
        m_index=None
        for i,j in enum(lst):
            if j>m: 
                m=j
                m_index=i
    
        if m_index:        
            largest=largest+[m_index]
            lst[m_index]=minval       
    
    print largest  
    

    这行得通。它很聪明。带那个老师!!!但是,你会得到一个 C 或更低的分数......

    或者——你可以成为老师的宠物。写成她想要的样子。您将需要一个列表的递归最大值。剩下的很简单!

    def max_of_l(l):
        if len(l) <= 1:
            if not l:
                raise ValueError("Max() arg is an empty sequence")
            else:
                return l[0]
        else:
            m = max_of_l(l[1:])
            return m if m > l[0] else l[0]
    
    print max_of_l([3, 8, 1, 2, 0, 4, 8, 5])        
    

    【讨论】:

    • 为什么非pythonic枚举如此复杂? def enum: for i in range(len(lst)): yield i,lst[i] 甚至内联enum = (i,lst[i] for i in range(len(lst)))。但无论如何枚举绝对等同于禁止enumerate..
    • @akaRem:我想可以做到。然而,我并没有试图简洁。我喜欢你的模组...
    猜你喜欢
    • 2020-04-28
    • 2019-02-13
    • 2022-06-13
    • 2017-06-25
    • 2019-02-17
    • 2022-01-13
    • 2017-03-15
    • 2011-03-10
    • 2022-01-05
    相关资源
    最近更新 更多