快速排序
快速排序有两点要注意:
一、partition分区算法的选择:
- 简单分区算法:选择一个基数,遍历数组元素和基数比较,如果元素nums[left]比基数大,就和数组nums[right]交换,right–,如果元素nums[left]比基数小,left++
- 双指针分区算法:从left和right分别定义一个指针,如果元素nums[left]比基数大,暂停遍历,如果元素nums[left]比基数小,left++;如果元素nums[right]比基数小,暂停遍历,如果元素nums[right]比基数大,right–;两边都暂停后互相交换元素,之后继续遍历,直到left和right指针相遇
二、基数的选择:随意选择区间内任何一个数字做基数都可以。有两种选择方式: - 选择第一个元素或者最后一个元素作为基数
- 选择区间内一个随机元素作为基数
第二种选择方式的平均时间复杂度是最优的,一般为O(nlogn),第一种在数组基本有序的情况下容易造成一边倒的结果,算法效率不高,时间复杂度为O(n^2)
相关算法题:leetcode-912
func quickSort(nums []int,start,end int){
if start>=end{
return
}
mid:=partition(nums,start,end)
quickSort(nums,start,mid-1)
quickSort(nums,mid+1,end)
}
简单分区算法
使用数组第一个元素作为基数pivot(leetcode结果大概为70-90ms)
func partition(nums []int,start,end int)int{
pivot:=nums[start]//使用数组第一个元素作为基数
left:=start+1
right:=end
for left<right{
if nums[left]>pivot{
nums[left],nums[right]=nums[right],nums[left]
right--
}else{
left++
}
}
if nums[left]>pivot{
nums[left-1],nums[start]=nums[start],nums[left-1]
return left-1
}else{
nums[left],nums[start]=nums[start],nums[left]
return left
}
}
使用数组中间元素作为基数pivot(leetcode结果大概为40-50ms)
func partition(nums []int,start,end int)int{
pivot:=nums[start+(end-start