classSolution: defMySort(self , arr ): # write code here # return sorted(arr) #冒泡排序 O(n**2) n = len(arr) left = 0 while left < n-1: right = left + 1 while right < n: if arr[left] > arr[right]: arr[left], arr[right] = arr[right], arr[left] right += 1 left += 1 return arr
桶排序 Bucket Sort
基本思路是:
将待排序元素划分到不同的痛。先扫描一遍序列求出最大值 maxV 和最小值 minV ,设桶的个数为 k ,则把区间 [minV, maxV] 均匀划分成 k 个区间,每个区间就是一个桶。将序列中的元素分配到各自的桶。 对每个桶内的元素进行排序。可以选择任意一种排序算法, 将各个桶中的元素合并成一个大的有序序列。
假设数据是均匀分布的,则每个桶的元素平均个数为 n/k 。假设选择用快速排序对每个桶内的元素进行排序,那么每次排序的时间复杂度为 O(n/klog(n/k)) 。总的时间复杂度为 O(n)+O(k)O(n/klog(n/k)) = O(n+nlog(n/k)) = O(n+nlogn-nlogk 。当 k 接近于 n 时,桶排序的时间复杂度就可以金斯认为是 O(n) 的。即桶越多,时间效率就越高,而桶越多,空间就越大。
classSolution: defMySort(self , arr ): # write code here deffind_smallest(arr): mini = float('inf') res = -1 for index, a inenumerate(arr): if mini > a: mini = a res = index return res res = [] n = len(arr) for _ inrange(n): smallest = find_smallest(arr) res.append(arr.pop(smallest)) return res
快速排序 Quick Sort
本质:分而治之 (Divide and Conquer, D&C)
找基准值 (pivot element)
分区 (partitioning)
虚假的快排
1 2 3 4 5 6 7 8 9 10 11
classSolution: defMySort(self , arr ): # write code here # 快速排序 iflen(arr) < 2: return arr else: pivot = arr[0] less = [i for i in arr[1:] if i <= pivot] greater = [i for i in arr[1:] if i > pivot] return self.MySort(less) + [pivot] + self.MySort(greater)
真实的快排
一. 挖坑填数分区法
1 2 3 4 5 6 7 8 9 10
defpartition1(arr, left, right): """挖坑填数""" pivot = arr[left] while left < right: while left < right and arr[right] >= pivot: right -= 1 if left < right: arr[left] = arr[right] while left < right and arr[left] <= pivot: left += 1 if left < right: arr[right] = arr[left] arr[left] = pivot return left
defpartition2(arr, left, right): """双指针交换""" pivot = arr[left] index = left while left < right: while left <= right and arr[left] <= pivot: left += 1 while left <= right and arr[right] >= pivot: right -= 1 if left > right: break arr[left], arr[right] = arr[right], arr[left] arr[index], arr[right] = arr[right], arr[index] return right
defpartition2_mid(arr, left, right): """双指针交换 + 三数取中优化""" mid = (left + right) >> 1 if arr[left] > arr[right]: arr[left], arr[right] = arr[right], arr[left] if arr[mid] > arr[right]: arr[mid], arr[right] = arr[right], arr[mid] if arr[mid] > arr[left]: arr[mid], arr[left] = arr[left], arr[mid] pivot = arr[left] index = left while left < right: while left <= right and arr[left] <= pivot: left += 1 while left <= right and arr[right] >= pivot: right -= 1 if left > right: break arr[left], arr[right] = arr[right], arr[left] arr[index], arr[right] = arr[right], arr[index] return right