LeetCode-Py数组排序算法全解:冒泡/选择/插入排序实现与优化
在日常开发中,排序算法是处理数据的基础工具。当面对小规模数据或基本有序的数组时,冒泡排序、选择排序和插入排序这三种简单排序算法往往是首选。本文将详细解析这三种算法的实现原理、优化技巧及适用场景,帮助读者快速掌握基础排序算法的核心要点。
冒泡排序:相邻元素的比较与交换
冒泡排序(Bubble Sort)通过重复遍历数组,比较相邻元素并交换位置,使较大元素逐步"冒泡"到数组末尾。算法核心是通过n-1趟比较,每趟将未排序区间的最大值移动到正确位置。
基本实现与优化
基础实现中,外层循环控制排序趟数,内层循环执行相邻元素比较交换。关键优化是引入swapped标志,当某趟未发生交换时说明数组已有序,可提前终止排序。
class Solution:
def bubbleSort(self, nums: [int]) -> [int]:
n = len(nums)
for i in range(n - 1):
swapped = False # 优化标志
for j in range(n - i - 1):
if nums[j] > nums[j + 1]:
nums[j], nums[j + 1] = nums[j + 1], nums[j]
swapped = True
if not swapped: # 无交换时提前退出
break
return nums
算法特性分析
| 指标 | 复杂度 | 说明 |
|---|---|---|
| 最佳时间复杂度 | $O(n)$ | 数组已有序时,仅需1趟比较 |
| 最坏时间复杂度 | $O(n^2)$ | 数组逆序时,需n-1趟比较 |
| 空间复杂度 | $O(1)$ | 原地排序,仅使用常数空间 |
| 稳定性 | 稳定 | 相等元素相对位置保持不变 |
适用场景与局限
冒泡排序适用于数据量较小(n<50)且基本有序的场景。官方文档中提供了完整的算法步骤图解和示例:数组冒泡排序。
选择排序:寻找最小元素的高效交换
选择排序(Selection Sort)通过将数组分为有序和无序区间,每趟从未排序区间选择最小元素,交换到有序区间末尾。相比冒泡排序,选择排序显著减少了交换次数。
核心实现逻辑
算法维护两个区间:已排序区间[0, i-1]和未排序区间[i, n-1]。每次迭代从无序区间找到最小元素位置,与无序区间首个元素交换,逐步扩大有序区间。
class Solution:
def selectionSort(self, nums: [int]) -> [int]:
n = len(nums)
for i in range(n - 1):
min_i = i # 最小元素索引
for j in range(i + 1, n):
if nums[j] < nums[min_i]:
min_i = j
if i != min_i: # 避免不必要交换
nums[i], nums[min_i] = nums[min_i], nums[i]
return nums
算法特性分析
| 指标 | 复杂度 | 说明 |
|---|---|---|
| 时间复杂度 | $O(n^2)$ | 无论数据状态,需固定次数比较 |
| 空间复杂度 | $O(1)$ | 原地排序,仅使用常数空间 |
| 稳定性 | 不稳定 | 交换操作可能改变相等元素顺序 |
与冒泡排序的对比
选择排序交换次数为O(n),远少于冒泡排序的O(n²),在数据交换成本较高场景更具优势。详细算法步骤可参考:数组选择排序。
插入排序:构建有序序列的高效方法
插入排序(Insertion Sort)将数组分为有序和无序区间,每次取出无序区间首个元素,插入到有序区间的正确位置。算法模拟手动整理扑克牌的过程,对基本有序数据效率极高。
算法实现与优化
内层循环使用while结构从后向前比较,将大于当前元素的元素依次后移,为待插入元素腾出位置。相比冒泡排序,插入排序减少了不必要的比较次数。
class Solution:
def insertionSort(self, nums: [int]) -> [int]:
for i in range(1, len(nums)):
temp = nums[i] # 待插入元素
j = i
while j > 0 and nums[j - 1] > temp:
nums[j] = nums[j - 1] # 元素后移
j -= 1
nums[j] = temp # 插入到正确位置
return nums
算法特性分析
| 指标 | 复杂度 | 说明 |
|---|---|---|
| 最佳时间复杂度 | $O(n)$ | 数组有序时,仅需n-1次比较 |
| 最坏时间复杂度 | $O(n^2)$ | 数组逆序时,需n(n-1)/2次比较 |
| 空间复杂度 | $O(1)$ | 原地排序,使用常数空间 |
| 稳定性 | 稳定 | 相等元素保持原有顺序 |
适用场景
插入排序特别适合处理以下场景:
- 数据量较小(n<50)
- 数据基本有序(如接近排序的日志数据)
- 在线排序(数据实时到达的流处理)
完整算法解析可参考官方文档:数组插入排序。
三种排序算法的综合对比与应用
性能对比矩阵
| 算法 | 平均时间复杂度 | 空间复杂度 | 稳定性 | 交换次数 | 适用场景 |
|---|---|---|---|---|---|
| 冒泡排序 | $O(n^2)$ | $O(1)$ | 稳定 | $O(n^2)$ | 基本有序小数据 |
| 选择排序 | $O(n^2)$ | $O(1)$ | 不稳定 | $O(n)$ | 交换成本高场景 |
| 插入排序 | $O(n^2)$ | $O(1)$ | 稳定 | $O(n^2)$ | 在线排序/基本有序 |
实际应用建议
在LeetCode刷题中,这三种排序算法可用于以下场景:
- 辅助理解复杂排序算法的基础原理
- 解决小规模排序问题(如n<50的场景)
- 实现特定场景的排序需求(如稳定排序)
相关练习题目:
算法选择决策树
通过理解这三种基础排序算法的原理与特性,能为学习高级排序算法(如归并排序、快速排序)打下坚实基础。实际开发中,应根据数据规模、有序程度和稳定性需求选择合适算法,或直接使用编程语言内置的高效排序函数。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



