[leetcode]归并&快排&堆思想题(python)

本文详细介绍了多种排序算法的实现,包括堆排序、快速排序和归并排序,以及如何找到数组中的第K个最大元素。此外,还探讨了数据流中中位数的实时计算以及在两个正序数组中寻找中位数的方法。这些算法在时间和空间复杂度上都有不同的权衡,对于理解和优化算法性能非常有帮助。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

数组中的第K个最大元素

法1:

用堆API做

def kthmaxnum(nums, k):
    heap = []
    for num in nums:
        heapq.heappush(heap, num)
        if len(heap) > k:
            heapq.heappop(heap)
    return heap[0]
  • 时间复杂度:O(nlogk)
  • 空间复杂度:O(k)

法2:

自己实现堆做

def kthMaxNum(nums, k):

    #把num放进最小堆heap里
    def heappush(heap,num):
        heap.append(num)
        i = len(heap) - 1
        while i > 1 and heap[i] < heap[i // 2]:
            heap[i], heap[i // 2] = heap[i // 2], heap[i]
            i = i // 2
        
    #删除heap里最小的元素
    def heappop(heap):
        n = len(heap) - 1
        heap[1], heap[n] = heap[n], heap[1]
        endnum = heap.pop()
        #下沉第一个元素
        i = 1
        n -= 1
        while i * 2 <= n:
            less = i * 2
            if i * 2 + 1 <= n and heap[i * 2 + 1] < heap[i * 2]:
                less = i * 2 + 1
            if heap[less] > heap[i]:
                break
            heap[i], heap[less] = heap[less], heap[i]
            i = less
        return endnum
       
    res = [None]
    for num in nums:
        heappush(res, num)
        if len(res) - 1 > k:
            heappop(res)
    return heappop(res)

法3:

快排法

def findKthNum(nums, k):
    
    def partition(left,right):
        if left == right:
            return left
        rand = random.randint(left, right)
        nums[left], nums[rand] = nums[rand], nums[left]
        pivot = nums[left]
        i = left + 1
        j = right
        while True:
            while i < right and nums[i] <= pivot:
                i += 1
            while j > left and nums[j] >= pivot:
                j -= 1
        	if i >= j:
                break
            nums[i], nums[j] = nums[j], nums[i]
        nums[left], nums[j] = nums[j], nums[left]
        return j
    
    left = 0
    right = len(nums) - 1
    n = len(nums)
    while left <= right:
        pos = partition(left, right)
        if pos == n - k:
            return nums[pos]
        elif pos > n - k:
            right = pos - 1
        else:
            left = pos + 1
    return None
  • 时间复杂度:O(n)
  • 空间复杂度:O(1)

自己实现最小堆

class myHeap:
    def __init__(self):
        self.heap = [0]
        self.N = 0
        
    def parent(self,root):
        return root // 2
    
    def left(self,root):
        return root * 2
    
    def right(self,root):
        return root * 2 + 1
    
    """
    def minnum(self):
        return self.heap[1]
    """
    
    #上浮第k个元素
    def swim(self,k):
        while k > 1 and self.heap[self.parent(k)] > k:
            self.heap[k], self.heap[self.parent(k)] = self.heap[self.parent(k)], self.heap[k]
            k = self.parent(k)
        
    #下沉第k个元素
    def sink(self,k):
        while self.left(k) <= self.N:
            less = self.left(k)
            if self.right(k) <= self.N and self.heap[self.right(k)] < self.heap[self.left(k)]:
                less = self.right(k)
            if k < self.heap[less]:
                break
            self.heap[less], self.heap[k] = self.heap[k], self.heap[less]
            k = less
    
    #插入一个元素
    def insert(self,value):
        self.N += 1
        self.heap.append(value)
        self.swim(self.N)
    
    #删除最小元素
    def delMin(self):
        minValue = self.heap[1]
        self.heap[1], self.heap[N] = self.heap[N], self.heap[1]
        self.heap.pop()
        self.N -= 1
        self.sink(1)
        return minValue

堆排序

def sortArray(nums):
    def maxHepify(arr, i, end):
        j = 2 * i
        while j <= end:
            if j + 1 <= end and arr[j+1] > arr[j]:
                j += 1
            if arr[i] < arr[j]:
                arr[i], arr[j] = arr[j], arr[i]
                i = j
                j = 2 * i
            else:
                break
                
    n = len(nums)
    nums = [0] + nums
        
    for i in range(n//2, 0, -1): #非叶子节点才需要下沉
        maxHepify(nums, i, n)
        
    for j in range(n, 0, -1):
        nums[1], nums[j] = nums[j], nums[1]
        maxHeapify(nums, 1, j-1)
    return nums[1:]
  • 时间复杂度:O(nlogn)
  • 空间复杂度:O(1)

快速排序

def sortArray(self, nums: List[int]) -> List[int]:

    def partition(left,right):
        if left == right:
            return left
        rand = random.randint(left,right)
        nums[rand], nums[left] = nums[left], nums[rand]
        pivot = nums[left]

        i = left + 1
        j = right
        while True:
            while i < right and nums[i] <= pivot:
                i += 1
            while j > left and nums[j] >= pivot:
                j -= 1
            if i >= j :
                break
            nums[i], nums[j] = nums[j], nums[i]
        nums[left], nums[j] = nums[j], nums[left]
        return j

    n = len(nums)
    if n <= 1:
        return nums
        
    def sort_helper(left,right):
        if left >= right:
            return
        p = partition(left, right)
        sort_helper(left,p-1)
        sort_helper(p+1,right)


    sort_helper(0, n - 1)
    return nums
  • 时间复杂度:O(nlogn)
  • 空间复杂度:O(logn)

归并排序

def sortArray(nums):
    
    def merge_sort(arr,l,r):
        if l == r:
            return
        mid = l + (r - l) // 2
        merge_sort(arr, l, mid)
        merge_sort(arr, mid + 1, r)
        tmp = []
        i = l #前半段起点
        j = mid + 1 #后半段起点
        while i <= mid or j <= r:
            if i > mid or (j <= r and arr[j] < arr[i]):
                tmp.append(nums[j])
                j += 1
            else:
                tmp.append(nums[i])
                i += 1
        nums[l:r+1] = tmp
            
    
    n = len(nums)
    if n <= 1:
        return nums
    merge_sort(nums,0,n-1)
    return nums
  • 时间复杂度:O(nlogn)
  • 空间复杂度:O(n)

数据流的中位数

class MedianInData:
    def __init__(self):
        #左边最大堆,右边最小堆
        self.maxHeap = []
        self.minHeap = []
    def addNum(self,value):
        if not self.maxHeap or value <= -self.maxHeap[0]:
            heapq.heappush(self.maxHeap, -value)
            if len(self.maxHeap) > len(self.maxHeap) + 1:
                heapq.heappush(self.minHeap, - heapq.heappop(self.maxHeap))
        else:
            heapq.heappush(self.minHeap, value)
            if len(self.minHeap) > len(self.maxHeap):
                heapq.heappush(self.maxHeap, - heapq.heappop(self.minHeap))
    def findMedian(self):
        if len(self.maxHeap) == len(self.minHeap):
            return (- self.maxHeap[0] + self.minHeap[0]) / 2
        else:
            return - self.maxHeap[0]
  • 时间复杂度:
    • addNum: O(logn)
    • findMedian:O(1)
  • 空间复杂度:O(n)

寻找两个正序数组的中位数

def findMedian(nums1, nums2):
    
    def findkthnum(k):
        idx1 = 0
        idx2 = 0
        while True:
        	if idx2 == n:
            	return nums2[idx2 + k - 1]
            if idx1 == m:
                return nums1[idx1 + k - 1]
            if k == 1:
                return min(nums1[idx1],nums2[idx2])
        
            newidx1 = min(idx1 + k // 2 - 1, m - 1)
            newidx2 = min(idx2 + k // 2 - 1, n - 1)
            if nums1[newidx1] <= nums2[newidx2]:
                k -= newidx1 - idx1 + 1
                idx1 = newidx1 + 1
            else:
                k -= newidx2 - idx2 + 1
                idx2 = newidx2 + 1
    
    m = len(nums1)
    n = len(nums2)
    k = (m + n) // 2
    if (m + n) % 2 == 0:
        return (findkthnum(k) + findkthnum(k+1)) / 2
    else:
        return findkthnum(k+1)
  • 时间复杂度:O(log(m+n))
  • 空间复杂度:O(1)

数组中的逆序对

def reversePairs(nums):
    n = len(nums)
    if n <= 1:
        return 0
    
    def merge_sort(nums,left,right):
        if left >= right:
            return
        mid = left + (right - left) // 2
        merge_sort(nums, left, mid)
        merge_sort(nums, mid + 1, right)
        tmp = []
        i = left
        j = mid + 1
        while i <= mid or j <= right:
            if i > mid :
                tmp.append(nums[j])
                j += 1
            elif j > right or (nums[i] <= nums[j]):
                tmp.append(nums[i])
                i += 1
            else:
                tmp.append(nums[j])
                self.res += mid + 1 - i
                j += 1
                
        nums[left:right+1] = tmp
        
    self.res = 0
    merge_sort(nums, 0, n - 1)
    return self.res
  • 时间复杂度:O(nlogn)
  • 空间复杂度:O(n)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值