题目描述
把数组分成"已排序"和"未排序"两段。每趟在未排序段里找最小值,和未排序段的第一个交换。
输入 = [5, 2, 4, 1, 3]
输出 = [1, 2, 3, 4, 5]
思路解析
第 i 趟:从下标 i 到末尾扫一遍,记下最小值的位置,然后把它和 i 位置交换。这样下标 i 就确定了最终该放的数。
第 1 趟 · 扫描找最小:在整个数组里扫一遍,找到最小值 1(在下标 3)。
最小的 1 换到最前:把 1 和下标 0 交换,1 归位。已排序区 = [1]。
第 2 趟 · 在 [2,4,5,3] 找最小:在剩下的未排序区找最小 = 2(已在下标 1),不用换。已排序区扩到 [1,2]。
第 3 趟 · 最小 3 换上来:未排序区 [4,5,3] 的最小是 3,和下标 2 交换。3 归位。
第 4 趟 · 4 换到位:最后未排序区 [5,4] 的最小是 4,交换归位。剩下的 5 自动到位,全部有序。
选择排序的思路是“为每个位置选对的数”,冒泡是“让对的数浮上去”。同为 O(n²),但选择的交换更省。
参考代码(Python)
Python
1n = len(nums)
2for i in range(n - 1):
3 min_idx = i # 假设当前位最小
4 for j in range(i + 1, n): # 在未排序区找更小
5 if nums[j] < nums[min_idx]:
6 min_idx = j
7 nums[i], nums[min_idx] = nums[min_idx], nums[i] # 换到位复杂度分析
- 时间复杂度:O(n²) —— 比较次数固定,与初始无关
- 空间复杂度:O(1) —— 原地
套路模板
记住骨架:外层定位置、内层找最小下标、末尾一次交换。和“堆排序”思想相通——堆排是用堆更快地“选最大”。
Python
1for i in range(n - 1):
2 m = i
3 for j in range(i+1, n):
4 if a[j] < a[m]: m = j # 记最小下标
5 a[i], a[m] = a[m], a[i] # 一趟一次交换易错点
- ❌ 边找边交换 → ✅ 找到最小下标后再换一次(边找边换会多做无用交换、还可能破坏稳定)
- ❌ 内层从 i 开始 → ✅ 从 i+1 开始找(i 本身就是待放入的位置)
以上文字与上方动画完全同一思路:先看动画建立直觉 → 读文字巩固 → 关掉页面自己默写一遍代码,能写出来才算真的掌握。