快速排序

快速排序的核心在于中间值的选取,以及数组的划分
算法的思路是:

1.将数组切割成两半,保证左边的数值小于中点值p值,右半边数组的数值大于中点値p
    0.假设中点値p为第一个数,
    1.使用双指针:i位于指针头部(从第1个开始,因为0已经是p了),j位于指针尾部
        如果i指向的数值小于p,则i++往右移动,否则停下来(while)
        如果j指向的数值大于p,则j++向做移动,否则停下来 (while)
        如果两个指针都停下来了,就交换i,j处的数值
        如果i>=j,则跳出循环,因为此时已经确保了j处的指针的数值肯定是小于p的了,(i处的数值可能会大于p,这种一般是i>j了)
        同时交换j和0处的数值
2.分别对左半边和右半边数组重复以上步骤

这里以leetcode 912 题为例,这题可用快速排序实现,但是在选取中间值的时候需要随机一个值,不然很难过官方的测试用例。
这里我实现了for和while两个版本

def partition_for(nums,l,r):
    p_idx = random.randint(l,r)
    nums[p_idx],nums[r] = nums[r],nums[p_idx] #此时中点値已经挪到最右了
    i = l - 1 #i的目的是记录i所在的值比中点値大
    for j in range(l,r):
        if nums[j] < nums[r]: #j所在的值比中点値小
            i += 1 #小于才自增,大于不自增,目的是为了让i处的值大于中点値
            nums[i],nums[j] = nums[j],nums[i]
    #跳出循环后我们能保证 i的右边都已经是大于中点値的了(因为j肯定是比i先走的,j经历过的地方肯定都已经是没有小于中点値的了),但是i当前的值是小于中点値的(因为刚交换过了)
    i += 1
    nums[i],nums[r] = nums[r],nums[i]
    return i

def partition_while(nums,start,end):
    if start == end: 
        return end

    p_idx = random.randint(start,end)
    nums[start],nums[p_idx] = nums[p_idx],nums[start]
    p = nums[start]
    left = start 
    right = end
    while left < right:
        while left <= end and nums[left] <= p:
            left += 1
        while right >= start and nums[right] > p:
            right -= 1
        if left >= right:
            break 
        nums[left],nums[right] = nums[right],nums[left]
        #left停下来的时候肯定会保证left指向的数会大于p
        #right停下来的时候肯定会保证right指向的数会小于p
        #所以left遇到right停下来的时候,right当前的位置肯定是小于p的,但是right右边的值会大于p
    nums[right],nums[start] = nums[start],nums[right]
    return right


class Solution(object):
    def quickSort(self, nums, l, r):
        if r - l <= 0:
            return
        mid = partition_while(nums, l, r)
        self.quickSort(nums, l, mid - 1)
        self.quickSort(nums, mid + 1, r)
    def sortArray(self, nums):
        """
        :type nums: List[int]
        :rtype: List[int]
        """
        self.quickSort(nums,0,len(nums) - 1)
        return nums
posted @ 2022-03-11 11:38  橘楚  阅读(42)  评论(0)    收藏  举报