排序算法 (Sorting Algorithms)
排序算法 (Sorting Algorithms)
排序算法是计算机科学中最基础也是最重要的算法之一。不同的排序算法有不同的时间复杂度和空间复杂度。
基础排序算法
1. 冒泡排序 (Bubble Sort)
过程演示: [5,3,8,4,2]
步骤1: [3,5,8,4,2] 比较5,3
步骤2: [3,5,8,4,2] 比较5,8
步骤3: [3,5,4,8,2] 比较8,4
步骤4: [3,5,4,2,8] 比较8,2
...直到没有交换发生
def bubbleSort(arr):
n = len(arr)
for i in range(n):
for j in range(0, n-i-1):
if arr[j] > arr[j+1]:
arr[j], arr[j+1] = arr[j+1], arr[j]
2. 选择排序 (Selection Sort)
过程演示: [5,3,8,4,2]
步骤1: [2,3,8,4,5] 找最小值2
步骤2: [2,3,8,4,5] 找剩余最小值3
步骤3: [2,3,4,8,5] 找剩余最小值4
步骤4: [2,3,4,5,8] 找剩余最小值5
def selectionSort(arr):
for i in range(len(arr)):
min_idx = i
for j in range(i+1, len(arr)):
if arr[j] < arr[min_idx]:
min_idx = j
arr[i], arr[min_idx] = arr[min_idx], arr[i]
3. 插入排序 (Insertion Sort)
过程演示: [5,3,8,4,2]
步骤1: [3,5,8,4,2] 插入3
步骤2: [3,5,8,4,2] 插入8
步骤3: [3,4,5,8,2] 插入4
步骤4: [2,3,4,5,8] 插入2
def insertionSort(arr):
for i in range(1, len(arr)):
key = arr[i]
j = i-1
while j >= 0 and arr[j] > key:
arr[j+1] = arr[j]
j -= 1
arr[j+1] = key
高级排序算法
1. 快速排序 (Quick Sort)
过程演示: [5,3,8,4,2], 选择5为pivot
步骤1: [3,4,2] 5 [8] 分区
步骤2: [2] 3 [4] 5 [8] 递归排序
结果: [2,3,4,5,8]
def quickSort(arr, low, high):
def partition(low, high):
pivot = arr[high]
i = low - 1
for j in range(low, high):
if arr[j] <= pivot:
i += 1
arr[i], arr[j] = arr[j], arr[i]
arr[i+1], arr[high] = arr[high], arr[i+1]
return i + 1
if low < high:
pi = partition(low, high)
quickSort(arr, low, pi-1)
quickSort(arr, pi+1, high)
2. 归并排序 (Merge Sort)
过程演示: [5,3,8,4]
分解: [5,3] [8,4]
[5] [3] [8] [4]
合并: [3,5] [4,8]
[3,4,5,8]
def mergeSort(arr):
if len(arr) > 1:
mid = len(arr)//2
L = arr[:mid]
R = arr[mid:]
mergeSort(L)
mergeSort(R)
i = j = k = 0
while i < len(L) and j < len(R):
if L[i] <= R[j]:
arr[k] = L[i]
i += 1
else:
arr[k] = R[j]
j += 1
k += 1
while i < len(L):
arr[k] = L[i]
i += 1
k += 1
while j < len(R):
arr[k] = R[j]
j += 1
k += 1
3. 堆排序 (Heap Sort)
过程演示: [5,3,8,4,2]
构建最大堆:
8
/ \
4 5
/ \
2 3
提取最大值:
8 [4,3,5,2]
5 [4,3,2]
4 [3,2]
3 [2]
2 []
def heapSort(arr):
def heapify(n, i):
largest = i
l = 2 * i + 1
r = 2 * i + 2
if l < n and arr[l] > arr[largest]:
largest = l
if r < n and arr[r] > arr[largest]:
largest = r
if largest != i:
arr[i], arr[largest] = arr[largest], arr[i]
heapify(n, largest)
n = len(arr)
# 构建最大堆
for i in range(n//2-1, -1, -1):
heapify(n, i)
# 一个个提取元素
for i in range(n-1, 0, -1):
arr[0], arr[i] = arr[i], arr[0]
heapify(i, 0)
经典问题
1. 数组中的第K个最大元素
LeetCode 215 - Kth Largest Element in an Array
使用快速选择算法:
输入: [3,2,1,5,6,4], k=2
快速选择过程:
1. 选择4为pivot: [3,2,1,4,6,5]
2. 4的位置是第3大,需要在右半部分继续查找
3. 选择5为pivot: [5,6]
4. 5是第2大的元素,返回5
def findKthLargest(nums, k):
def quickSelect(left, right, k):
pivot = nums[right]
p = left
for i in range(left, right):
if nums[i] <= pivot:
nums[p], nums[i] = nums[i], nums[p]
p += 1
nums[p], nums[right] = nums[right], nums[p]
count = right - p + 1
if count == k:
return nums[p]
elif count > k:
return quickSelect(p+1, right, k)
else:
return quickSelect(left, p-1, k-count)
return quickSelect(0, len(nums)-1, k)
2. 合并区间
先排序后合并:
输入: [[1,3],[2,6],[8,10],[15,18]]
排序后:
[1,3],[2,6],[8,10],[15,18]
↓
合并[1,3]和[2,6]:
[1,6],[8,10],[15,18]
输出: [[1,6],[8,10],[15,18]]
def merge(intervals):
if not intervals:
return []
# 按开始时间排序
intervals.sort(key=lambda x: x[0])
merged = [intervals[0]]
for interval in intervals[1:]:
if interval[0] <= merged[-1][1]:
merged[-1][1] = max(merged[-1][1], interval[1])
else:
merged.append(interval)
return merged
3. 排序链表
使用归并排序:
输入: 4->2->1->3
分解:
4->2->1->3
4->2 1->3
4 2 1 3
合并:
2->4 1->3
1->2->3->4
def sortList(head):
if not head or not head.next:
return head
# 找到中点
slow = fast = head
prev = None
while fast and fast.next:
fast = fast.next.next
prev = slow
slow = slow.next
prev.next = None
# 递归排序
l1 = sortList(head)
l2 = sortList(slow)
# 合并
dummy = ListNode(0)
curr = dummy
while l1 and l2:
if l1.val <= l2.val:
curr.next = l1
l1 = l1.next
else:
curr.next = l2
l2 = l2.next
curr = curr.next
curr.next = l1 or l2
return dummy.next
4. 颜色分类
使用三指针(荷兰国旗问题):
输入: [2,0,2,1,1,0]
过程:
[2,0,2,1,1,0] p0=0, p2=5
[0,0,2,1,1,2] p0=2, p2=4
[0,0,1,1,2,2] p0=2, p2=3
输出: [0,0,1,1,2,2]
def sortColors(nums):
p0 = curr = 0
p2 = len(nums) - 1
while curr <= p2:
if nums[curr] == 0:
nums[p0], nums[curr] = nums[curr], nums[p0]
p0 += 1
curr += 1
elif nums[curr] == 2:
nums[curr], nums[p2] = nums[p2], nums[curr]
p2 -= 1
else:
curr += 1
高级应用
1. 外部排序
大文件排序:
1. 分块读入内存
2. 对每块排序
3. 归并所有块
2. 多路归并
K个有序数组:
[1,4,7]
[2,5,8] → 归并 → [1,2,3,4,5,6,7,8,9]
[3,6,9]
3. 计数排序
输入: [4,2,2,8,3,3,1]
计数数组:
索引: 0 1 2 3 4 5 6 7 8
计数: 0 1 2 2 1 0 0 0 1
输出: [1,2,2,3,3,4,8]
常见技巧
- 选择合适的排序算法
- 自定义比较函数
- 处理特殊情况
- 稳定性考虑
- 空间复杂度优化
相关题目
- LeetCode 147 - Insertion Sort List
- LeetCode 179 - Largest Number
- LeetCode 274 - H-Index
- LeetCode 315 - Count of Smaller Numbers After Self
- LeetCode 912 - Sort an Array