在算法面试和实际工程中,"215.数组中的第K个最大元素"是一个经典的分治算法问题。给定整数数组nums和整数k,我们需要找到排序后数组中第k个最大的元素。这个问题看似简单,但蕴含着多种算法思路和优化空间。
实际应用场景包括:
最直观的解法是将数组排序后直接取第k个元素:
python复制def findKthLargest(nums, k):
nums.sort()
return nums[-k]
时间复杂度:O(nlogn)
空间复杂度:O(1)
注意:虽然代码简洁,但当n很大时排序整个数组会造成不必要的性能浪费。
更优的解法是使用堆数据结构:
python复制import heapq
def findKthLargest(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)
这种方法只需维护大小为k的最小堆,适合处理海量数据流。
基于快速排序的分治思想,可以实现更优的O(n)平均时间复杂度:
python复制import random
def findKthLargest(nums, k):
def partition(left, right, pivot_index):
pivot = nums[pivot_index]
nums[pivot_index], nums[right] = nums[right], nums[pivot_index]
store_index = left
for i in range(left, right):
if nums[i] < pivot:
nums[store_index], nums[i] = nums[i], nums[store_index]
store_index += 1
nums[right], nums[store_index] = nums[store_index], nums[right]
return store_index
def select(left, right, k_smallest):
if left == right:
return nums[left]
pivot_index = random.randint(left, right)
pivot_index = partition(left, right, pivot_index)
if k_smallest == pivot_index:
return nums[k_smallest]
elif k_smallest < pivot_index:
return select(left, pivot_index - 1, k_smallest)
else:
return select(pivot_index + 1, right, k_smallest)
return select(0, len(nums) - 1, len(nums) - k)
实际项目中可以结合多种策略:
| 方法 | 时间复杂度(平均) | 时间复杂度(最坏) | 空间复杂度 | 适用场景 |
|---|---|---|---|---|
| 排序法 | O(nlogn) | O(nlogn) | O(1) | 小规模数据 |
| 堆排序 | O(nlogk) | O(nlogk) | O(k) | 数据流处理 |
| 快速选择 | O(n) | O(n^2) | O(1) | 随机访问数据 |
实际编码中需要考虑:
python复制def findKthLargest(nums, k):
if not nums or k < 1 or k > len(nums):
raise ValueError("Invalid input")
# 其余实现代码...
不同编程语言可以利用其特性优化实现:
C++版本可以利用nth_element:
cpp复制int findKthLargest(vector<int>& nums, int k) {
nth_element(nums.begin(), nums.begin()+k-1, nums.end(), greater<int>());
return nums[k-1];
}
Java版本可以使用PriorityQueue:
java复制public int findKthLargest(int[] nums, int k) {
PriorityQueue<Integer> heap = new PriorityQueue<>();
for (int num : nums) {
heap.add(num);
if (heap.size() > k) {
heap.poll();
}
}
return heap.peek();
}
在推荐系统中,我们需要从百万级商品库中快速找出最可能被用户喜欢的Top K商品。使用堆排序方法可以高效处理:
python复制def get_top_k_recommendations(item_scores, k):
heap = []
for item_id, score in item_scores.items():
heapq.heappush(heap, (score, item_id))
if len(heap) > k:
heapq.heappop(heap)
return [item_id for (score, item_id) in heap]
类似的问题变种包括:
对于海量数据场景,可以考虑:
面试官通常会考察:
常见follow-up问题:
在实际编码中,我发现这些技巧很有帮助:
快速选择算法的实现容易出错,特别注意:
最后分享一个调试技巧:在分区过程中打印数组状态,可以直观看到算法执行过程:
python复制def partition(left, right, pivot_index):
print(f"Partitioning {left} to {right} with pivot={nums[pivot_index]}")
# ...其余代码...
print(f"After partitioning: {nums[left:right+1]}")
return store_index