Sorting

merge sort

LC 148: sort a linked list

快慢指针分成两半,断开中间,分别递归排序,最后升序合并两个链表。边界条件:head==None or head.next==None

LC 23. Merge k Sorted Lists

注意边界情况

quick sort

以数组某个元素(一般选取首元素)为基准数,将所有小于基准数的元素移动至其左边,大于基准数的元素移动至其右边。 python模版

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
def partition(nums, left, right):
    pivot = nums[left]#初始化一个待比较数据
    i,j = left, right
    while(i < j):
        while(i<j and nums[j]>=pivot): #从后往前查找,直到找到一个比pivot更小的数
            j-=1
        nums[i] = nums[j] #将更小的数放入左边
        while(i<j and nums[i]<=pivot): #从前往后找,直到找到一个比pivot更大的数
            i+=1
        nums[j] = nums[i] #将更大的数放入右边
    #循环结束,i与j相等
    nums[i] = pivot #待比较数据放入最终位置 
    return i #返回待比较数据最终位置

def quickSort(self, nums, low, high):
    if low<high:
        pivot=self.partition(nums, low, high)
        
        self.quickSort(nums,low, pivot-1)
        self.quickSort(nums, pivot+1, high)

215 数组中的第K个最大元素

视频讲解

期望为线性的选择算法.

函数返回时,第m+1小的元素正好在m这个 index 上。并且比它小的都在它左边,比它大的都在它右边。

避免超时:三路划分

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

def three_way_partition(nums, low, high):
    # 随机选择基准元素并交换到最左端(避免最坏情况)
    rand_pivot = random.randint(low, high)
    nums[low], nums[rand_pivot] = nums[rand_pivot], nums[low]
    pivot = nums[low]

    # 初始化三个指针:
    # [low..lt] < pivot
    # [lt+1..i) == pivot
    # [gt..high] > pivot
    lt = low          # 左区间的右边界(最后一个 < pivot 的位置)
    gt = high + 1     # 右区间的左边界(第一个 > pivot 的位置)
    i = low + 1       # 当前扫描指针

    while i < gt:
        if nums[i] < pivot:
            lt += 1
            nums[i], nums[lt] = nums[lt], nums[i]
            i += 1
        elif nums[i] > pivot:
            gt -= 1
            nums[i], nums[gt] = nums[gt], nums[i]
        else:
            i += 1
    
    # 将基准元素交换到中间区间的起始位置
    nums[low], nums[lt] = nums[lt], nums[low]
    lt -= 1  # 现在 [low..lt] < pivot, [lt+1..gt-1] == pivot, [gt..high] > pivot

    # 返回左区间右边界和右区间左边界
    return lt, gt

递归函数

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
def quickSort(self, nums, low, high,m):
    if low<high:
        # 调用三路划分模版
        lt, gt = self.partition(nums, low, high)
        # 判断目标位置所在的区间
        if m <= lt:        # 目标在左区间
            return self.quickSort(nums, low, lt, m)
        elif m >= gt:      # 目标在右区间
            return self.quickSort(nums, gt, high, m)
        else:                   # 目标在中间区间(直接命中)
            return nums[m]