- 冒泡排序
关键词:两两交换
① 初级算法
def bubbleSort(nums):
n = len(nums)
for i in range(n - 1):
for j in range(1, n - i):
if nums[j - 1] > nums[j]:
nums[j - 1], nums[j] = nums[j], nums[j - 1]
return nums
② 优化手段: 当本地循环未发生任何的交换时,则认为数组已经有序,无需继续遍历
def bubbleSort(nums):
n = len(nums)
for i in range(n - 1):
flag = False
for j in range(n - i - 1):
if nums[j] > nums[j + 1]:
flag = True
nums[j], nums[j + 1] = nums[j + 1], nums[j]
if not flag: # 未交换
break
return nums
③ 优化手段: 记录每次遍历中最后交换的元素index,下次遍历时无需再进行到 n - i的位置
def bubbleSort(nums):
n = len(nums)
indexOfLastUnsortedIndex = n - 1
swipped = True
swippedIndex = -1
while swipped:
swipped = False
for index in range(indexOfLastUnsortedIndex):
if nums[index] < nums[index + 1]:
nums[index], nums[index + 1] = nums[index + 1], nums[index]
swipped = True
swippedIndex = index
indexOfLastUnsortedIndex = swippedIndex
return nums
稳定的排序算法
时间复杂度: 以上的优化手段,最好的情况下只需要O(n)的时间复杂度(数组已有序的情况下),但平均时间复杂度仍然是O(n^2).
空间复杂度: O(1)。
- 选择排序
关键词: 每轮选择一个最值
① 初级算法
def selectionSort(nums):
n = len(nums)
for i in range(n - 1):
minIndex = i
for j in range(i + 1, n):
if nums[j] < nums[minIndex]:
minIndex = j
nums[i], nums[minIndex] = nums[minIndex], nums[i]
return nums
② 优化手段: 二元选择,每轮同时选择最大值和最小值
def selectionSort(nums):
n = len(nums)
# 外层遍历
for i in range(n // 2):
minIndex, maxIndex = i, i
for j in range(i + 1, n - i):
if nums[j] > nums[maxIndex]:
maxIndex = j
if nums[j] < nums[minIndex]:
minIndex = j
// 相等表示: 此时后续位置已经处于"平均值",无需再排序
if minIndex == maxIndex: break
# min
nums[minIndex], nums[i] = nums[i], nums[minIndex]
# max
if maxIndex == i: maxIndex = minIndex
nums[maxIndex], nums[n - i - 1] = nums[n - i - 1], nums[maxIndex]
return nums
在外层遍历中,只需要遍历 n//2 次。这是因为每轮都会查找到两个最值,而且无需考虑奇偶数情况(因为如果处于奇数,其他元素都排好序了剩余的一个元素一定是"被迫"有序)。
不稳定的排序算法
时间复杂度: 优化后的算法平均时间复杂度仍然为O(n^2)
空间复杂度: O(1)
- 插入排序
关键词: 将index元素插入前置已排好序的数组中
① 交换法: 不断的与前面数字交换,直到找到合适的位置
def insertSort(nums):
n = len(nums)
# 外层遍历: 从第二个元素开始
for i in range(1, n):
j = i - 1
while j >= 0 and nums[j] > nums[j + 1]:
# 直接替换元素
nums[j], nums[j + 1] = nums[j + 1], nums[j]
j -= 1
return nums
② 移动法: 不断的比较,前面的数字向后挪出位置,然后找到后一举插入
def insertSort(nums):
n = len(nums)
for i in range(1, n):
cur = nums[i]
j = i - 1
while j >= 0 and nums[j] > cur:
nums[j + 1] = nums[j]
# 每次循环,其实都是在准确位置的前一个位置
j -= 1
nums[j + 1] = cur
return nums
稳定的排序算法
空间复杂度: O(1)