快排-写法一
取一哨兵,左边的元素比它小,右边的元素比它大。
PS: ① 记得返回 当没有数据要处理 或者 只有一个数据时候(即左边下标>=右边下标时)
② 每次队规任务是 将数组分成两组 左边组是小于第一个元素的 右边组是大于第一个元素的 结束后下标left指向右边组第一个元素 right指向左边组最后一个元素
③ 要保证当元素个数大于等于2时是可以进去的 所以在外层循环条件是 left<=right (内不循环 除了判断大于小于benchmark,其余 left<=right)
复杂度: 时间复杂度O(nlogn) 空间复杂度O(1)
def quicksort(nums, start, end):
# start > end 证明没有数据要处理
# start = end 证明只有一个数据要处理
if start >= end:
return
benchmark = nums[start]
left, right = start + 1, end # 可能会出现 end = start+1 即 left = right
# 经过while循环的目的是交换分为左右两组,左边组小 右边组大 且right是小于benchmark的最后一个元素
while left <= right: # 等号保证当 left=right 如 2 1这种情况也能进去
# 下面两个循环是过滤掉左侧比 benchmark小于等于的 右边比benchmark大于的
while left <= right and nums[left] < benchmark: # 1 2时 left = 1
left += 1
while right >= left and nums[right] > benchmark: # 1 2时 right = 0
right -= 1
# 判断是否需要交换 如果是 1 2 的话 left=1 right=0 已经不需要交换
if left <= right:
nums[left], nums[right] = nums[right], nums[left]
left, right = left+1, right-1
# 交换 right和start对应位置的元素
nums[start], nums[right] = nums[right], nums[start]
quicksort(nums, start, right-1)
quicksort(nums, right+1, end)
nums = [2, 1, 5, 6, 5, 4]
quicksort(nums, 0, len(nums)-1)
print(nums)
快排-写法二
一行代码实现排序
时间复杂度 nlog(n) 空间复杂度 O(1)
注意: 表达式中 arr[0:1] 不能直接 arr[0] ,应该是一个列表。 或者可以写为 [arr[0]]
qsort = lambda arr: len(arr) > 1 and qsort(list(filter(lambda x: x <= arr[0], arr[1:]))) + arr[0:1] + qsort(list(filter(lambda x: x > arr[0], arr[1:]))) or arr
对应理解
'''
① lambda表达式
sum = lambda a,b: a+b
sum(1,3)
def sum(a,b):
return a+b
sum(1,3)
② and 和 or
and
or 前一个为真返回前边的值 如果前一个为假 返回后边一个
③ filter:用于过滤序列,过滤掉不符合条件的元素,返回符合条件的元素组成新列表 (类型是filter 如果想转换为列表则用list()转换)
filter(function,iterable)
序列中的每个元素作为参数传递给函数进行判断,返回True或者False,最后将返回True的元素放到新列表中。
# 返回比a[0]小的元素
def f(x):
return x<=a[0]
对应 lambda表达式 lambda x: x<a[0]
# 返回奇数
def f(x):
return x%2 == 1
'''
def qsort1(arr):
if len(arr) <= 1:
return arr
leftnum = list(filter(lambda x: x <= arr[0], arr[1:]))
rightnum = list(filter(lambda x: x > arr[0], arr[1:]))
return qsort1(leftnum) + arr[0:1] + qsort1(rightnum)
进一步简化
简单解释: 找到
时间复杂度 nlog(n) 空间复杂度 O(n)
def qsort2(nums):
if len(nums) <= 1:
return nums
leftnum, rightnum = [], []
benchmark = nums[0]
nums.remove(benchmark)
for item in nums:
if item <= benchmark:
leftnum.append(item)
else:
rightnum.append(item)
return qsort2(leftnum)+[benchmark]+qsort2(rightnum)