You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Kth smallest元素大根堆Python解法Time limit exceeded问题求助

Kth smallest element 题目调试

我在练习GeeksForGeeks平台的Kth smallest element题目,题目详情如下:

给定数组 arr[] 和整数 K,其中K小于数组长度,任务是查找给定数组中的**第K小(Kth smallest)**元素,题目保证所有数组元素互不相同。

预期时间复杂度(Expected Time Complexity): O(n)
预期辅助空间(Expected Auxiliary Space): O(log(n))
约束条件(Constraints):

  • 1 <= N <= 10^5
  • 1 <= arr[i] <= 10^5
  • 1 <= K <= N

我的实现代码

class Solution:
    def kthSmallest(self,arr, l, r, k):
        '''
        arr : given array
        l : starting index of the array i.e 0
        r : ending index of the array i.e size-1
        k : find kth smallest element and return using this function
        '''
        arr2=arr[:k]
        arr2.insert(0,None)
        for i in range(k//2,0,-1):
            arr2=self.heapify(arr2,i,k-1)
            
        for i in arr[k:]:
            if i <arr2[1]:
                arr2[1]=i
                arr2=self.heapify(arr2,1,k-1)
        return arr2[1]


    def heapify(self,arr, i, r):
        if 2 * i <= r + 1 and arr[2 * i] > arr[i]:
            arr[2 * i], arr[i] = arr[i], arr[i * 2]
            arr = self.heapify(arr, 2 * i, r)
        if 2 * i + 1 <= r + 1 and arr[2 * i + 1] > arr[i]:
            arr[2 * i + 1], arr[i] = arr[i], arr[i * 2 + 1]
            arr = self.heapify(arr, 2 * i + 1, r)
        return arr

我的实现思路为:首先截取数组前K个元素构建子数组,对其执行大根堆化(max heapify)操作;随后遍历数组剩余元素,若当前元素小于堆顶元素,则替换堆顶元素后对堆顶执行max heapify操作。运行代码时出现**时间超限(Time limit exceeded)**错误,需要定位问题诱因与优化方案。


问题原因与优化方案

超时核心原因

  • 递归实现堆化的开销过高:Python函数递归调用的栈帧开销远大于迭代逻辑,在1e5量级的数据规模下,频繁递归会大幅拖慢运行速度。
  • 存在额外的线性时间开销:arr2.insert(0, None)是数组头部插入操作,时间复杂度为O(k),当k接近1e5时这一步就会消耗大量运行时间;每次递归返回后重新给arr2赋值也会产生不必要的对象操作开销。
  • 堆化逻辑有冗余:左子节点交换完成后直接递归下沉,之后没有更新当前节点的最大值状态就直接判断右子节点,会产生重复比较,增加无效计算。
  • 算法复杂度不满足题目要求:大小为K的大根堆找第K小的时间复杂度是O(n logk),当K和数组长度同量级时,复杂度接近O(n logn),达不到题目要求的O(n)时间复杂度,自然容易触发时间限制。

可落地的优化方案

1. 堆逻辑优化(可通过用例,但不满足最优复杂度要求)

去掉头部占位的冗余插入操作,把递归堆化改成迭代实现,堆化时每次统一比较当前节点和左右子节点的最大值,只做一次交换后循环下沉,消除递归和冗余判断的开销。
优化后的堆实现代码:

class Solution:
    def kthSmallest(self,arr, l, r, k):
        def max_heapify(heap, i, heap_size):
            while True:
                left = 2 * i + 1
                right = 2 * i + 2
                largest = i
                if left < heap_size and heap[left] > heap[largest]:
                    largest = left
                if right < heap_size and heap[right] > heap[largest]:
                    largest = right
                if largest == i:
                    break
                heap[i], heap[largest] = heap[largest], heap[i]
                i = largest
        
        heap = arr[:k]
        # 原地建大根堆
        for i in range(k//2 - 1, -1, -1):
            max_heapify(heap, i, k)
        # 遍历剩余元素维护堆
        for num in arr[k:]:
            if num < heap[0]:
                heap[0] = num
                max_heapify(heap, 0, k)
        return heap[0]

2. 快速选择算法(完全匹配题目复杂度要求)

基于快速排序分区思想实现快速选择,每次随机选取基准值将数组划分为小于基准、大于基准两部分,根据基准最终落点和K的位置关系,只需要递归处理其中一个分区,平均时间复杂度O(n),递归栈空间平均O(logn),完全符合题目要求。随机选基准的操作可以避免有序数组下的最坏时间复杂度问题。
快速选择实现代码:

import random
class Solution:
    def kthSmallest(self,arr, l, r, k):
        target = k - 1
        while l <= r:
            # 随机选基准规避最坏情况
            pivot_pos = random.randint(l, r)
            arr[pivot_pos], arr[r] = arr[r], arr[pivot_pos]
            pivot = arr[r]
            i = l
            # 分区:小于基准的放左边,大于的放右边
            for j in range(l, r):
                if arr[j] < pivot:
                    arr[i], arr[j] = arr[j], arr[i]
                    i += 1
            arr[i], arr[r] = arr[r], arr[i]
            # 匹配目标位置直接返回
            if i == target:
                return arr[i]
            elif i < target:
                l = i + 1
            else:
                r = i - 1

内容的提问来源于stack exchange,提问作者Debjyoti Sutradhar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 12:19:50