返回
数组中的第 K 个最大元素:剖析题目精髓,轻松寻找数组中的王者
前端
2024-01-16 02:30:00
题目分析
给定一个整数数组 nums 和一个整数 k,要求返回数组中第 k 个最大的元素。需要注意的是,这里所说的第 k 个最大元素,指的是数组排序后的第 k 个最大元素,而不是第 k 个不同的元素。
解法一:快速选择
快速选择算法是一种非常高效的排序算法,它可以快速地找到数组中的第 k 个最大元素。算法的核心思想是将数组划分为两个部分,一部分包含比第 k 个最大元素大的元素,另一部分包含比第 k 个最大元素小的元素。然后,通过递归地应用快速选择算法,可以在线性时间内找到第 k 个最大元素。
步骤如下:
- 选择数组中的一个元素作为枢轴元。
- 将数组划分为两个部分,一部分包含比枢轴元大的元素,另一部分包含比枢轴元小的元素。
- 如果枢轴元恰好是第 k 个最大元素,则直接返回枢轴元。
- 如果枢轴元比第 k 个最大元素大,则在包含比枢轴元小的元素的部分继续搜索。
- 如果枢轴元比第 k 个最大元素小,则在包含比枢轴元大的元素的部分继续搜索。
代码示例:
def find_kth_largest(nums, k):
"""
快速选择算法找到数组中的第 k 个最大元素。
参数:
nums: 输入的整数数组。
k: 要找的第 k 个最大元素。
返回:
数组中第 k 个最大的元素。
"""
def partition(nums, left, right):
"""
对数组进行划分,返回枢轴元的位置。
参数:
nums: 输入的整数数组。
left: 左边界。
right: 右边界。
返回:
枢轴元的位置。
"""
pivot = nums[right]
i = left - 1
for j in range(left, right):
if nums[j] <= pivot:
i += 1
nums[i], nums[j] = nums[j], nums[i]
nums[i + 1], nums[right] = nums[right], nums[i + 1]
return i + 1
def quick_select(nums, left, right, k):
"""
快速选择算法找到数组中的第 k 个最大元素。
参数:
nums: 输入的整数数组。
left: 左边界。
right: 右边界。
k: 要找的第 k 个最大元素。
返回:
数组中第 k 个最大的元素。
"""
if left == right:
return nums[left]
pivot_index = partition(nums, left, right)
if pivot_index == k:
return nums[pivot_index]
elif pivot_index > k:
return quick_select(nums, left, pivot_index - 1, k)
else:
return quick_select(nums, pivot_index + 1, right, k)
if k <= 0 or k > len(nums):
raise ValueError("k must be between 1 and the length of the array.")
return quick_select(nums, 0, len(nums) - 1, k - 1)
时间复杂度:
快速选择算法的平均时间复杂度为 O(n),最坏情况下的时间复杂度为 O(n^2)。
空间复杂度:
快速选择算法的空间复杂度为 O(1)。
解法二:堆排序
堆排序是一种基于二叉堆的数据结构的排序算法。堆排序的思想是将数组中的元素构建成一个二叉堆,然后不断地从堆顶弹出元素,并将其插入到数组的尾部,直到堆为空。这样,数组中的元素就按照从大到小的顺序排列好了。
步骤如下:
- 将数组中的元素构建成一个二叉堆。
- 从堆顶弹出元素,并将其插入到数组的尾部。
- 重建二叉堆。
- 重复步骤 2 和步骤 3,直到堆为空。
代码示例:
def find_kth_largest(nums, k):
"""
堆排序算法找到数组中的第 k 个最大元素。
参数:
nums: 输入的整数数组。
k: 要找的第 k 个最大元素。
返回:
数组中第 k 个最大的元素。
"""
def heapify(nums, n, i):
"""
将数组中的元素构建成一个二叉堆。
参数:
nums: 输入的整数数组。
n: 数组的长度。
i: 当前节点的位置。
"""
largest = i
left = 2 * i + 1
right = 2 * i + 2
if left < n and nums[left] > nums[largest]:
largest = left
if right < n and nums[right] > nums[largest]:
largest = right
if largest != i:
nums[i], nums[largest] = nums[largest], nums[i]
heapify(nums, n, largest)
def build_heap(nums):
"""
将数组中的元素构建成一个二叉堆。
参数:
nums: 输入的整数数组。
"""
n = len(nums)
for i in range(n // 2 - 1, -1, -1):
heapify(nums, n, i)
def heap_sort(nums):
"""
堆排序算法对数组进行排序。
参数:
nums: 输入的整数数组。
"""
build_heap(nums)
n = len(nums)
for i in range(n - 1, 0, -1):
nums[0], nums[i] = nums[i], nums[0]
heapify(nums, i, 0)
heap_sort(nums)
return nums[k - 1]
时间复杂度:
堆排序算法的平均时间复杂度为 O(n log n),最坏情况下的时间复杂度为 O(n log n)。
空间复杂度:
堆排序算法的空间复杂度为 O(1)。
总结
快速选择算法和堆排序算法都是非常高效的算法,都可以用于找到数组中的第 k 个最大元素。快速选择算法的平均时间复杂度为 O(n),而堆排序算法的平均时间复杂度为 O(n log n)。在实际应用中,可以根据具体情况选择合适的算法。