快排算法的程序结构:
def quicksort(nums, l, r):
if l >= r:
return
k = partition(nums, l, r)
quicksort(nums, l, k - 1)
quicksort(nums, k + 1, r)
其中partition函数输入参数是一个数组nums和两个位置索引l
和r
,输出为位置索引k。需要满足:
而一般的partition函数的实现不仅能够满足上述两个条件,还会更严格,如把第二个条件中的其中一个等号去掉:
不但能够用来排序,还能做其它事情。
如下版本返回值k,均满足 n u m s [ l . . k − 1 ] < n u m s [ k ] nums[l..k-1] < nums[k] nums[l..k−1]<nums[k] 且 n u m s [ k + 1.. r ] ≥ n u m s [ k ] nums[k+1..r]\ge nums[k] nums[k+1..r]≥nums[k]
for
循环遍历基准元素左侧所有元素,里指针s所指元素及其左侧元素都是小于最右侧基准元素nums[r]
。for
循环,s再前进一位,所指元素与基准元素对调,以确保最终的列表里其右侧元素均大于等于其所指元素。for
循环里以指针i
为核心,其向右遍历,如果小于基准元素,则替换以大于等于基准元素。def partition(nums, l, r):
s = l - 1
for i in range(l, r):
if nums[i] < nums[r]:
s += 1
if s != i:
nums[s], nums[i] = nums[i], nums[s]
s += 1
nums[s], nums[r] = nums[r], nums[s]
return s
i==j
且nums[l..i-1],nums[i+1..r]>=x
。
- 然后根据
nums[i]
与x的大小关系,分三种情况处理,并决定返回值:if nums[i] > x:
nums[i], nums[r] = x, nums[i]
elif nums[i] < x:
i += 1
if nums[i] > x:
nums[i], nums[r] = x, nums[i]
def partition3(nums, l, r):
x = nums[r]
i, j = l, r-1
while i < j:
while nums[i] < x and i < j: # 循环终止时i满足nums[i]>=x或者i==j
i += 1
while nums[j] >= x and i < j: # 循环终止时j满足nums[j]
j -= 1
if j > i: # 说明必有nums[i]>=x且nums[j]
nums[i], nums[j] = nums[j], nums[i]
if nums[i] < x:
i += 1
nums[i], nums[r] = x, nums[i]
return i
class Solution(object):
def findKthLargest(self, nums, k):
if len(nums) == 0 or k <= 0 or k > len(nums):
return None
i, j = 0, len(nums)-1
k = len(nums) - k
while True:
ix = partition(nums, i, j)
if ix == k:
return nums[ix]
elif ix < k:
i = ix + 1
else:
j = ix - 1
用快排的partition方法来找到第k大的数,那么该数以及其左侧k-1个数一起,就是最小的k个数。
class Solution:
def GetLeastNumbers_Solution(self, tinput, k):
if tinput is None or len(tinput) < k or k <= 0:
return []
s, t = 0, len(tinput)-1
while True:
ix = partition(tinput, s, t)
print(s,t,ix)
if ix == k -1:
return sorted(tinput[:k])
elif ix > k -1:
t = ix -1
else:
s = ix + 1
len(numbers)>>1
上出现,因此用partition函数找到该数,然后检查其是否满足条件即可。len(numbers)>>1
这个下标,直到二者相等。如果有出现次数超过一半的数,则必然是该下标的元素。究竟是不是,也要检查一番才能确定。len(numbers)>>1
这个下标左侧的元素却是小于等于该下标所指元素。只是由while True
循环里对s
和t
的更新方式导致的。class Solution:
def MoreThanHalfNum_Solution(self, numbers):
def checkMoreThanHalf(num, numbers):
half = (len(numbers)>>1)+1 # 一半加一
for n in numbers:
if n == num:
half -= 1
return half <= 0
if len(numbers) == 0:
return 0
s, t = 0, len(numbers)-1
mid = len(numbers)>>1
while True:
ix = partition(numbers, s, t)
print(s,t, ix, numbers)
if ix > mid:
t = ix - 1
elif ix < mid:
s = ix + 1
else:
break
num = numbers[mid]
return num if checkMoreThanHalf(num, numbers) else 0