排序不只是调用sort(),理解排序思想是解决TopK和区间问题的钥匙
排序是算法的基础中的基础。面试中,你不需要手写快排,但需要理解各种排序的特点:哪些稳定、哪些原地、哪些 O(n log n)、哪些可以 O(n)。更重要的是,排序常作为其他算法的预处理步骤——排序 + 双指针、排序 + 二分、排序 + 贪心。
sort(key=..., reverse=...)。# list.sort() — 原地排序
nums = [3, 1, 4, 1, 5]
nums.sort() # [1, 1, 3, 4, 5]
nums.sort(reverse=True) # [5, 4, 3, 1, 1]
# sorted() — 返回新列表
new_list = sorted(nums)
# 自定义 key
words = ["banana", "pie", "Washington"]
words.sort(key=len) # 按长度: ["pie", "banana", "Washington"]
words.sort(key=lambda x: x.lower()) # 忽略大小写
# 多关键字排序
students = [("Alice", 90), ("Bob", 85), ("Charlie", 90)]
students.sort(key=lambda x: (-x[1], x[0])) # 分数降序,名字升序
题目描述:给定整数数组 nums 和整数 k,请返回数组中第 k 个最大的元素。
class Solution:
def findKthLargest(self, nums: List[int], k: int) -> int:
# 方法二: 小顶堆
import heapq
heap = []
for num in nums:
heapq.heappush(heap, num)
if len(heap) > k:
heapq.heappop(heap)
return heap[0]
时间复杂度:O(n log k)
空间复杂度:O(k)
题目描述:给你一个整数数组 nums 和一个整数 k,请你返回其中出现频率前 k 高的元素。
class Solution:
def topKFrequent(self, nums: List[int], k: int) -> List[int]:
from collections import Counter
import heapq
count = Counter(nums)
return heapq.nlargest(k, count.keys(), key=count.get)
时间复杂度:O(n log k) — nlargest 内部用堆
空间复杂度:O(n)
题目描述:给你一个整数数组 nums,请你将该数组升序排列。要求时间复杂度 O(n log n)。
class Solution:
def sortArray(self, nums: List[int]) -> List[int]:
if len(nums) <= 1:
return nums
mid = len(nums) // 2
left = self.sortArray(nums[:mid])
right = self.sortArray(nums[mid:])
return self._merge(left, right)
def _merge(self, left, right):
result = []
i = j = 0
while i < len(left) and j < len(right):
if left[i] <= right[j]:
result.append(left[i])
i += 1
else:
result.append(right[j])
j += 1
result.extend(left[i:])
result.extend(right[j:])
return result
时间复杂度:O(n log n)
空间复杂度:O(n)
面试中很少要求手写排序,但排序作为预处理步骤的场景非常多。这里总结排序在面试中的实战策略。
许多看似需要 O(n²) 的问题,排序后用双指针可以降到 O(n log n + n)。
# 排序 + 双指针的典型场景
# 两数之和(有序版)、三数之和、最接近的三数之和
# 关键: 排序后可以根据大小关系决定指针移动方向
def twoSumSorted(nums, target):
nums.sort() # O(n log n)
left, right = 0, len(nums) - 1
while left < right: # O(n)
s = nums[left] + nums[right]
if s == target:
return [left, right]
elif s < target:
left += 1
else:
right -= 1
Python 的 sort 支持任意 key 函数,灵活运用可以简化很多问题。
# 按多个条件排序
# 例: 先按分数降序,同分按名字升序
students.sort(key=lambda x: (-x.score, x.name))
# 按自定义规则排序
# 例: 重新排列日志(字母日志在前,数字在后)
logs.sort(key=lambda x: (x.split()[1].isdigit(),
x.split()[1:], x.split()[0]))