三路快排算法-求中位数问题(4)

简介: 算法面试高频题,求前K个数,或者求中位数引至51CTO三路快排算法思路将数组分为三部分,随机选择数组中的一个数,使数组左边都小于这个数,右边大于这个数。

算法面试高频题,求前K个数,或者求中位数

引至51CTO

三路快排算法思路

  1. 将数组分为三部分,随机选择数组中的一个数,使数组左边都小于这个数,右边大于这个数。
  2. 在递归处理左边数组,右边数组。

step1排列数组的时间复杂度是O(N),空间复杂度是O(1)
step2 递归调用的复杂度O(logN)

总体的时间赋值度O(NlogN)

Step 1 算法解释

    def __QuickSort(self,a,l,r):
        #a[l,r)
        if(l+1>=r):
            return
        rand_index = random.randint(l,r-1) 
        self.swap(a,l,rand_index) ## 对已经排好序的数组,有优化作用
        gt = r ##右边的指针位置
        lt = l ##左边的指针位置
        i = l+1 ## 遍历指针
        while(i<gt): ##遍历条件
            if(a[i]>a[l]):
                self.swap(a,i,gt-1)
                gt = gt -1 ##将大数换到右端,大数指针--
            elif(a[i]<a[l]):
                self.swap(a,lt+1,i)
                i = i+1
                lt= lt+1 ## 将小数换到左端,小数指针--
            else:
                i = i+1 ## 相等的数据,步进指针++
        self.swap(a,l,lt) ##将小数的最后一个和第一个数交换,结果是[l,lt)是小数
        self.__QuickSort(a,gt,r)
        self.__QuickSort(a,l,lt) ##递归调用

求中位数算法

利用快速排序思想,只处理中位数所在的区域(中数、大数或小数)

  • 中位数在大数区,对大数区快速排序
  • 中位数在小数区,对小数区快速排序
  • 中位数在中数区,返回

考虑中位数是len//2,len//2-1情况

def __swap(a,i,j):
    tmp  = a[i]
    a[i] = a[j]
    a[j] = tmp
    
def insertSort(a,l,r):
    #a[l,r)
    i = l
    while(i<r):
        j = i
        while(j>l):
            if (a[j]<a[j-1]):
                __swap(a,j,j-1)                
            else:
                break 
            j = j-1
        i = i+1

def sortMid(a):
    mid = len(a)//2
    sortHead(a,mid)
    
def sortHead(a,k):
    #a[l,r)
    assert(k<len(a))
    __sortHead(a,0,len(a),k)

def __sortHead(a,l,r,k):
    if(r-l<10):
        insertSort(a,l,r)
        return    
    rand = random.randint(l,r-1)
    __swap(a,l,rand)
    
    lt = l
    gt = r
    i  = l
    while(i<gt):
        if(a[i]>a[l]):
            __swap(a,gt-1,i)
            gt = gt -1
        elif(a[i]<a[l]):
            __swap(a,lt+1,i)
            i= i +1
            lt = lt + 1
        else:
            i = i+1
    __swap(a,lt,l)
## 判断k在哪个区域
    if(k-1<lt):
        ## 将k-1也进行排序,考虑len//2-1
        __sortHead(a,l,lt,k)
    if(k>=gt):
        __sortHead(a,gt,r,k)

测试代码

import copy
for i in range(50):
    total = random.randint(0,200000)
    a = np.random.randint(0,total,500000)
    a.tolist()
    b =  copy.copy(a)
    a.sort()
    mid1 = a[len(a)//2]
    mid1_left = a[len(a)//2-1]
    sortMid(b)
    mid2 = b[len(a)//2]
    mid2_left = b[len(a)//2-1]
    if(mid1 == mid2 and mid1_left==mid2_left):
        print("True")
    else:
        print("Flase")
目录
相关文章
|
7月前
|
算法 测试技术 C++
【动态规划】【中位数】【C++算法】1478. 安排邮筒
【动态规划】【中位数】【C++算法】1478. 安排邮筒
|
算法 测试技术 C#
C++前缀和算法的应用:统计中位数为 K 的子数组
C++前缀和算法的应用:统计中位数为 K 的子数组
|
7月前
|
算法
【MATLAB】语音信号识别与处理:移动中位数滤波算法去噪及谱相减算法呈现频谱
【MATLAB】语音信号识别与处理:移动中位数滤波算法去噪及谱相减算法呈现频谱
97 2
|
7月前
|
算法
LeetCode算法题---无重复字符的最长子串、寻找两个正序数组的中位数(三)
LeetCode算法题---无重复字符的最长子串、寻找两个正序数组的中位数(三)
65 0
|
算法 C++
剑指offer(C++)-JZ41:数据流中的中位数(算法-排序)
剑指offer(C++)-JZ41:数据流中的中位数(算法-排序)
剑指offer(C++)-JZ41:数据流中的中位数(算法-排序)
|
5月前
|
人工智能 算法
算法金 | 平均数、众数、中位数、极差、方差,标准差、频数、频率 一“统”江湖
**统计学江湖概要** - **平均数(均值)**:数字的总和除以数量,代表集中趋势,如分赃时平均分配。 - **众数**:出现次数最多的数字,反映了最常见的值,如同一招式被频繁使用。 - **中位数**:排序后位于中间的值,反映数据的中心位置,如同武者武功的中等水平。 - **极差**:最大值减最小值,表示数据波动范围,类似武功最高与最低的差距。 - **方差**:衡量数据波动性,计算每个数值与均值差的平方和的平均数。 - **标准差**:方差的平方根,同单位的波动度量。 - **频数**:某个值出现的次数,如统计武器使用情况。 - **频率**:频数与总次数的比例,显示出现的相对频率。
100 2
算法金 | 平均数、众数、中位数、极差、方差,标准差、频数、频率 一“统”江湖
|
7月前
|
搜索推荐 算法 索引
【排序算法】深入解析快速排序(霍尔法&&三指针法&&挖坑法&&优化随机选key&&中位数法&&小区间法&&非递归版本)
【排序算法】深入解析快速排序(霍尔法&&三指针法&&挖坑法&&优化随机选key&&中位数法&&小区间法&&非递归版本)
184 4
|
7月前
|
搜索推荐 算法 大数据
13.经典 O(nlogn) 复杂度算法之快排
13.经典 O(nlogn) 复杂度算法之快排
158 1
|
7月前
|
搜索推荐 算法 大数据
经典 O(nlogn) 复杂度算法之快排
经典 O(nlogn) 复杂度算法之快排
58 0
|
7月前
|
算法 搜索推荐 Java
【算法系列篇】分治-快排
【算法系列篇】分治-快排