时间复杂度O(N*logN)
额外空间复杂度O(logN)
可以用荷兰国旗问题来改进快速排序==>随机
把一个数组分为较小和较大的2个子序列,然后递归地排序两个子序列
经典快排
- 挑选基准值:从数列中挑出一个元素,称为"基准"(pivot)
- 分割:重新排序数列
- 所有比基准值小的元素摆放在基准前面
- 所有比基准值大的元素摆在基准后面
- 与基准值相等的数可以到任何一边(或者中间)
- 在这个分割结束之后,对基准值的排序就已经完成
- 递归排序子序列:递归地将小于基准值元素的子序列和大于基准值元素的子序列排序
递归到最底部的判断条件是数列的大小是零或一,此时该数列显然已经有序;
选取基准值有数种具体方法,此选取方法对排序的时间性能有决定性影响(使用随机
)
class QuickSort(object):
"""
快排
经典快排
随机快排
"""
def run(self, arr: list):
if arr is None or len(arr) < 2:
return
self.quick_sort(arr, 0, len(arr) - 1)
def quick_sort(self, arr, L, R):
if L < R:
p = self.partition(arr, L, R)
self.quick_sort(arr, L, p[0] - 1)
self.quick_sort(arr, p[0] + 1, R)
def partition(self, arr: list, L: int, R: int):
less = L - 1
more = R
while L < more:
if arr[L] < arr[R]:
arr[less], arr[L] = arr[L], arr[less]
less += 1
L += 1
elif arr[L] > arr[R]:
arr[more], arr[L] = arr[L], arr[more]
more -= 1
else:
L += 1
arr[more], arr[R] = arr[R], arr[more]
return [less + 1, more]
list_ = [1, 3, 3, 5, 4, 2, 1, 5, 8, 7, 9]
result = QuickSort().run(list_)
print(result)
class QuickSortPython:
def partition(self, arr, low, high):
i = low - 1 # 最小元素索引
pivot = arr[high]
# pivot = random.choice(arr) # 随机快排
for j in range(low, high):
if arr[j] <= pivot: # 当前元素小于或等于 pivot
i += 1
arr[i], arr[j] = arr[j], arr[i]
arr[i + 1], arr[high] = arr[high], arr[i + 1]
return i + 1
def sort(self, arr, low, high):
"""
:param arr: 排序数组
:param low: 起始索引
:param high: 结束索引
:return:
"""
if low < high:
pi = self.partition(arr, low, high)
self.sort(arr, low, pi - 1)
self.sort(arr, pi + 1, high)
return arr
list_ = [1, 3, 3, 5, 4, 2, 1, 5, 8, 7, 9]
result = QuickSortPython().sort(list_, 0, len(list_) - 1)
print(result)
荷兰国旗
给定一个数组arr,和一个数num
请把小于num的数放在数组的 左边,等于num的数放在数组的中间,大于num的数放在数组的 右边。
要求额外空间复杂度O(1),时间复杂度O(N)
class HeLanGuoQi(object):
"""荷兰国旗问题"""
def partition(self, arr: list, num: int):
cur = 0
less = - 1
more = len(arr) - 1 + 1
while cur < more:
if arr[cur] < num:
less += 1
arr[less], arr[cur] = arr[cur], arr[less]
cur += 1
elif arr[cur] > num:
more -= 1
arr[more], arr[cur] = arr[cur], arr[more]
# cur -= 1 # TODO: 注意这里cur不动
else:
cur += 1
# 返回等与区域的左边界和右边界
return [less + 1, more - 1]
数组分组
给定一个数组arr,和一个数num,请把小于等于num的数放在数组的左边,大于num的数放在数组的右边。
要求额外空间复杂度O(1),时间复杂度O(N)
评论区