如何改进关于堆排序的Python代码?

如何改进关于堆排序的Python代码?,python,algorithm,sorting,heapsort,Python,Algorithm,Sorting,Heapsort,我尝试自己编写一个堆排序程序,如下所示,而不是使用Python内置的排序方法。Leetcode应该接受堆排序方法,但由于某些原因,我不知道,尽管我的堆排序程序工作得很好,但我仍然遭到Leetcode的运行时拒绝。有人能帮忙吗 已解决,下面的代码使用Floyd算法重新编辑以初始化堆,并已通过Leetcode def heapsort(nums): def swap(i, j): nums[i], nums[j] = nums[j], nums[i] def

我尝试自己编写一个堆排序程序,如下所示,而不是使用Python内置的排序方法。Leetcode应该接受堆排序方法,但由于某些原因,我不知道,尽管我的堆排序程序工作得很好,但我仍然遭到Leetcode的运行时拒绝。有人能帮忙吗

已解决,下面的代码使用Floyd算法重新编辑以初始化堆,并已通过Leetcode

def heapsort(nums):

    def swap(i, j):

        nums[i], nums[j] = nums[j], nums[i]


    def sift(start, size):

        l = (start << 1) + 1 # Do not forget () for <<
        r = l + 1
        largest = start
        if l <= size - 1 and nums[start] < nums[l]:
            largest = l
        if r <= size - 1 and nums[largest] < nums[r]:
            largest = r   
        if largest != start:
            swap(start, largest)
            sift(largest, size)


    size = len(nums)

    # Initialize heap (Floyd Algorithm)
    end = (size >> 1) - 1
    while end >= 0:
        sift(end, size)
        end -= 1
    swap(0, size - 1)
    size -= 1

    # Heapify recursively
    while size > 1:
        sift(0, size)
        swap(0, size - 1)
        size -= 1
def heapsort(nums):
def交换(i,j):
nums[i],nums[j]=nums[j],nums[i]
def筛选(开始,大小):
l=(开始1:
筛选(0,大小)
交换(0,大小-1)
尺寸-=1

堆排序,考虑Python模块。它是为了这个目的而存在的。提供堆队列算法的实现。它的设计不是很方便,但是很方便——你可以自己谷歌。
说到查找重复项,任何
n log(n)
排序算法都不应该足够有效。请看一下python内置算法!

您的代码做得太多了。您正在用删除的每个项重建整个堆。因此,O(n log n)算法应该是O(n^2)

基本上,您的代码就是这样做的:

while array is not empty
    rearrange array into a heap
    extract the smallest item
重新排列堆最多需要O(n)个时间。提取最小值需要O(logn)。因此,您的算法是O(n^2+n logn)

实际上,从下至上构建堆的方法本身就是O(n logn)。因此,堆排序算法实际上是O((n+1)*(n logn))。在任何情况下,它都是一个高度次优的算法

堆排序背后的思想是将数组一次性排列到堆中。这是一个O(n)操作。算法非常简单:

for i = heap.length/2 downto 1
    siftDown(i)
以其发明者的名字命名

注意,我们从数组的中间开始筛选。这个想法是,最后的N个/ 2个条目是叶节点,所以它们无论如何也不能筛选。从N/2开始,向后工作,我们可以在O(n)时间中整数组。

将数组排列成堆后,我们将执行以下操作:

while heap is not empty
    output the item at heap[0]
    move the item at the end of the heap to heap[0]
    reduce the count of items by 1
    siftDown(0)
堆[0]中的项是堆中剩余的最小项,因此我们将其输出。这样,就不需要重建整个堆。您所要做的就是获取堆中的最后一项,将其放在顶部,然后将其向下筛选到位。堆的其余部分仍然有效

进行这些更改应该会减少运行时间,尽管我不知道这是否会使您的代码可以接受。还有另一种方法可以检查重复项。它需要O(n)个额外空间,但比排序更快


其思想是创建一个哈希表,然后遍历数组,检查该项是否在哈希表中。如果不在,则添加它。如果它已经在表中,则它是重复的。正如Harold所指出的,Python有一种类型使这类事情变得容易。

这属于CodeReviewOrry,但coderview是什么?Stackoverflow上的一个模块或者什么?@Naomik抱歉,我应该链接。@NicholasLiu:你的代码能正常工作吗?我的堆排序程序运行得很好,似乎与Leetcode的运行时拒绝相矛盾。工作代码应该发布在codereview上进行审查。坏代码应该发布在Stack Overflow上,以帮助修复它。@Matt我改进了我的代码,只是在编辑了我的帖子(只需复制所有内容并粘贴到Leetcode 217,你就会知道所有内容)。但这一次,我仍然收到了超出时间限制的错误。我的堆排序代码能够按升序对列表进行排序,所以我想这可能是因为存在效率不高的地方,或者O(nlogn)对于Leetcode来说仍然被认为太慢。你是对的(谢谢你的长篇大论)。所以我刚刚编辑了我的代码,我首先像以前一样从列表中构建堆,这需要log(1)+log(2)+…+log(n)~nlog(n);接下来每次我移除顶层元素,并用堆的最后一个元素替换它,而不是将堆重建为采用nlog(n)的初始化,我应该像你说的那样筛选新的顶部元素。重点是,在筛选过程中,我的算法是每层向下的,我只是比较三角形上的节点(顶部节点三角形是我的新顶部元素),当新的顶部元素触底时,最坏需要2*log(n-1)。所以现在我的整个排序时间是nlog(n)+2log(n-1)+2log(n-2)+…+2log(1)~3nlog(n)~nlog(n)。不幸的是,我的程序仍然被拒绝,因为超过了时间限制。是的,我知道哈希和集合只使用O(n)更好,我编写堆排序只是为了好玩。@NicholasLiu:这更好,但是你可以使用Floyd的算法在O(n)时间内构建初始堆。