数据结构与算法-基础排序算法及TopK问题(Python)

2023-11-12

基础排序算法

如果在面试中遇到排序算法,先问清楚数据的特点,结合具体的业务场景,多和面试官交流,先陈述思路,得到面试官肯定以后再编码
没有一个排序算法是任何情况下都表现最好的。
学习算法的可视化网站:https://www.cs.usfca.edu/~galles/visualization/Algorithms.html

常见排序算法对比
在这里插入图片描述
所有代码和思路以升序为例。

冒泡排序

思路:

  • 每一轮依次比较相邻的两个元素,如果前一个元素>后一个,则交换位置,保证未排定部分的最大元素置于数组末尾;
  • 重复上述步骤,直到第2个元素是前两个元素中最大的,排序结束;

优化:
通过flag标识已经有序的情况,提前停止排序。

Python实现:

class Solution:
    def sortArray(self, nums: List[int]) -> List[int]:
        if len(nums)<2:
            return nums
        
        flag = True
        n = len(nums)
        for i in range(n,0,-1):
            for j in range(1,i):
                if nums[j-1]>nums[j]:
                    flag = False
                    nums[j-1],nums[j] = nums[j],nums[j-1]
            if flag:
                break
        return nums

复杂度分析:
时间复杂度:O(n2),加上flag最优的情况即本身有序,O(n);
空间复杂度:O(1),原地操作,不需要额外的空间。

选择排序

思路:

  • 每轮选出未排定部分中最小的元素,交换到未排定部分的开头,交换一次;

Python实现:

class Solution:
    def sortArray(self, nums: List[int]) -> List[int]:
        if len(nums)<2:
            return nums
        
        n = len(nums)
        for i in range(n):
            min_idx = i
            for j in range(i+1,n):
                if nums[j]<nums[min_idx]:
                    min_idx = j
            nums[i],nums[min_idx] = nums[min_idx],nums[i]

        return nums

复杂度分析:
时间复杂度:O(n2);
空间复杂度:O(1),原地操作,不需要额外的空间。

优点: 交换次数最少
在交换成本较高的排序任务中,可以使用选择排序。

插入排序

思路:

  • 保持当前元素左侧是排序后的数组,将当前元素插入到对应位置。

Python实现:

class Solution:
    def sortArray(self, nums: List[int]) -> List[int]:
        if len(nums)<2:
            return nums
        
        n = len(nums)
        for i in range(1,n):
            j = i 
            while j>0 and nums[j]<nums[j-1]:
                nums[j],nums[j-1] = nums[j-1],nums[j]
                j -= 1

        return nums

复杂度分析:
时间复杂度:O(n2),最好的情况即数组有序时,复杂度为O(n);
空间复杂度:O(1),原地操作,不需要额外的空间。

优化
可以采用二分查找的方式来确定需要插入的位置

优点:
内层循环可以提前终止,因此插入排序在几乎有序的数组上表现良好,在短数组(每个元素离它最终排定的位置都不会太远)上表现也很好。

归并排序

思路:

  • 分而治之的思想,理解递归的好材料,递归时,只剩下一个元素或没有元素时返回;
  • 借助额外空间,合并两个有序数组,得到更长的有序数组。

Python实现:

class Solution:
    def sortArray(self, nums: List[int]) -> List[int]:
        if len(nums)<2:
            return nums
  
        self.mergesort(nums,0,len(nums)-1)
        return nums
    
    def merge(self,nums,left,mid,right):
        temp = []
        i = left
        j = mid+1
        while i<=mid and j<=right:
            if nums[i]<=nums[j]:
                temp.append(nums[i])
                i += 1
            else:
                temp.append(nums[j])
                j += 1
        while i<=mid:
            temp.append(nums[i])
            i += 1
        while j<=right:
            temp.append(nums[j])
            j += 1
        return temp

    def mergesort(self,nums,left,right):
        if left>=right:
            return
        mid = (left+right)//2
        self.mergesort(nums,left,mid)
        self.mergesort(nums,mid+1,right)
        temp = self.merge(nums,left,mid,right)
        for j in range(len(temp)):
            nums[left+j] = temp[j]

复杂度分析:
时间复杂度:确定的O(nlogn)
空间复杂度:O(n),借助了额外空间,可以实现稳定排序

缺点:
需要额外的空间,元素来回复制;
一般不用于内排序。

优化:
只开一个temp数组,避免频繁申请、释放内存。

快速排序

思路:

  • 每论都排定一个元素(主元pivot),然后递归地去排它左侧和右侧的部分,直到数组有序
    Tips:
    随机化选择切分元素,否则在输入数组是有序或逆序时,快速排序会非常慢;
    递归到规模充分小时,停止递归,直接用简单排序(如插入排序)。

Python实现:

## 方法一:
class Solution:
    def sortArray(self, nums: List[int]) -> List[int]:
        if len(nums)<=1:
            return nums
        
        def partition(left,right):
            pivot = nums[left]
            index = left
            for i in range(left+1,right+1):
                if nums[i]<pivot:
                    index += 1
                    if i!=index:
                        nums[i],nums[index] = nums[index],nums[i]
            nums[left],nums[index] = nums[index],nums[left]
            return index
        
        def quicksort(low,high):
            if low<high:
                idx = partition(low,high)
                quicksort(low,idx-1)
                quicksort(idx+1,high)
            return

        quicksort(0,len(nums)-1)
        return nums
## 方法二:
def quickSort(self,nums,left,right):
        print(left,right,nums)
        if left>=right:
            return
        mid = (left+right)//2
        if nums[mid]<nums[left]:
            nums[mid],nums[left] = nums[left],nums[mid]
        if nums[right]<nums[left]:
            nums[right],nums[left] = nums[left],nums[right]
        if nums[mid]>nums[right]:
            nums[mid],nums[right] = nums[right],nums[mid]
        
        nums[mid],nums[right-1] = nums[right-1],nums[mid]
        #if right-left<=2:
        #    return
      
        pivot = nums[right-1]
        i = left
        j = right-1
        while i<j:
            i += 1
            j -= 1
            while nums[i]<pivot:
                i += 1
            while nums[j]>pivot:
                j -= 1
            if i<j:
                nums[i],nums[j] = nums[j],nums[i]
            else:
                break

        nums[i],nums[right-1] = nums[right-1],nums[i]
        print(nums)
        self.quickSort(nums,left,i-1)
        self.quickSort(nums,i+1,right)

复杂度分析:
时间复杂度:O(nlogn),最坏情况下O(n2)
空间复杂度:O(logn)

经典问题:TopK

TopK 是面试常考的问题
「力扣」第 215 题:数组中的第 K 个最大元素

堆排序

思路:
堆是对选择排序的优化,通过把未排定部分构建成堆,可以实现O(logn)选择最大的元素。

两个特性:

  1. 结构性:用数组表示的完全二叉树;
  2. 有序性:任一结点的关键字是其子树所有结点的最大值(或最小值)
    maxheap:最大堆,又叫大顶堆

python:heapq模块

Python实现:
维护一个k大小的小顶堆,顶部就是第k个大的元素,如果是取最大的k个元素一般直接用大顶堆;
heap数组大小设置为k+1,从下标为1开始存储元素,则下标为p的结点其左右子结点分别为2p/2p+1,其父节点为p//2。

class Solution:
    def findKthLargest(self, nums: List[int], k: int) -> int:
        if not nums or len(nums)<k:
            return -1
        
        heap = [0 for _ in range(k+1)]
        for i in range(k):
            heap[i+1] = nums[i]
        
        ## build the heap
        for i in range(k//2,0,-1):
            self.percdown(i,k,heap)
        ## insert
        for i in range(k,len(nums)):
            if nums[i]>heap[1]:
                heap[1] = nums[i]
                self.percdown(1,k,heap)
        return heap[1]

    def percdown(self,i,k,heap):
        while i*2<=k:
            if i*2+1<=k and heap[i*2+1]<heap[i*2]:
                Min = i*2+1
            else:
               Min = i*2
            if heap[i]>heap[Min]:
                heap[i],heap[Min] = heap[Min],heap[i]
            i = Min 

复杂度分析:
时间复杂度:O(nlogk)
空间复杂度:O(k)

空间复杂度与k相关,适用于海量的数据,不需要一次性完全读取。

快速排序

# TopK
class Solution:
    def findKthLargest(self, nums: List[int], k: int) -> int:
        if len(nums)<k:
            return -1
        
        small = len(nums)-k

        def partition(left,right):
            pivot = nums[left]
            index = left
            for i in range(left+1,right+1):
                if nums[i]<pivot:
                    index += 1
                    if i!=index:
                        nums[i],nums[index]=nums[index],nums[i]
            nums[left],nums[index] = nums[index],nums[left]
            if index==small:
                return 
            elif index<small:
                partition(index+1,right)
            else:
                partition(left,index-1)
        
        partition(0,len(nums)-1)
        return nums[small]

复杂度分析:
时间复杂度:O(n),根据主定理计算可得;
空间复杂度:O(logn),递归栈空间

参考资料
https://leetcode-cn.com/problems/sort-an-array/solution/dang-wo-tan-pai-xu-shi-wo-zai-tan-xie-shi-yao-by-s/
https://leetcode-cn.com/problems/sort-an-array/solution/fu-xi-ji-chu-pai-xu-suan-fa-java-by-liweiwei1419/

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

数据结构与算法-基础排序算法及TopK问题(Python) 的相关文章

随机推荐

  • Spring AOP:面向切面编程的简介和实践

    目录 一 什么是AOP 二 AOP的核心概念 三 Spring AOP的实现方式 第一种 注解配置AOP 第二种 xml配置AOP 一 什么是AOP AOP Aspect Oriented Programming 即面向切面编程 是一种编程
  • 在.NET中使用正则表达式(入门篇)

    转载请注明 敏捷学院 技术资源库 原文链接 http dev mjxy cn a In NET using regular expressions aspx 代码下载 RegexExample zip介绍正则表达式提供了功能强大 灵活而又高
  • ITest:京东数科接口自动化测试实践

    导读 你是否为每天 点点点 的工作而感到索然无味 你是否苦于没有合适的工具而对复杂的测试任务望而却步 频繁变动的接口 重复的功能测试 你 疲惫么 京东数科平台开发团队基于日常接口测试经验 开发了接口测试平台 ITest 通过此平台让研发流程
  • [OpenAirInterface实战-20] :OAI 软件无线电USRP E310硬件详解

    作者主页 文火冰糖的硅基工坊 文火冰糖 王文兵 的博客 文火冰糖的硅基工坊 CSDN博客 本文网址 https blog csdn net HiWangWenBing article details 121094384 第1章 概述 USR
  • ChatGPT 或其它 AI,能用在文书创作上吗?

    新的申请季已经正式开始 一些热门项目的ED截止日期也不再遥远 因此很多准留学生们都已经开始了关于文书的创作 而随着科技的不断发展 以ChatGPT为首的一众AI工具也作为一种辅助手段愈发融入了我们的生活 那么不免就会有一些同学在准备申请时
  • excel基本操作1

    excel隔行设置样式 条件格式 gt 条件规则 gt 输入公式 参考https jingyan baidu com article 36d6ed1f2379c35acf4883e0 html excel隔列取值 使用Index结合row和
  • 无线专题 osi模型、TCP/IP五层模型、网络编程(一)

    一 OSI介绍 1 OSI的来源 OSI Open System Interconnect 即开放式系统互联 一般都叫OSI参考模型 是ISO 国际标准化组织 组织在1985年研究的网络互连模型 ISO为了更好的使网络应用更为普及 推出了O
  • Kafka消费者详解

    一 Kafka消费者的消费模式 当生产者将消息发送到Kafka集群后 会转发给消费者进行消费 消息的消费模型有两种 推送模式 push 和拉取模式 pull 1 消息的推送模式 消息的推送模式需要记录消费者的消费状态 当把一条消息推送给消费
  • u盘刷新系统

    1 百度u盘制作将u盘进行刷成系统盘 点击添加系统 确认 关掉即可 到这里就制作完成了 u盘里也有系统了 下一步就是进入电脑的 bios 一般是f8 或者f2 或者esc 看你是什么电脑自己手机百度一下 当进入u盘系统时候会发现一键刷机工具
  • 【计算机网络】HTTP协议详解(八):HTTP网关

    HTTP网关 文章目录 HTTP网关 一 网关 Gateway 二 网关的分类 1 HTTP 服务器端网关 2 HTTP 客户端网关 3 HTTP HTTPS 服务器端安全网关 4 HTTPS HTTP 客户端安全加速器网关 5 资源网关
  • sshpass

    sshpass 安装 sshpass Linux 软件工具安装 源码安装 测试 sshpass 在使用 ssh scp 等命令进行远程操作的时候 必须手动输入密码 这就为自动化的执行造成困扰 sshpass 可以在命令行直接使用密码来进行远
  • Android Studio 常用快捷按键

    大小写转换 Cmd Shift U Ctrl Shift U 注释代码 Cmd Ctrl 注释代码 Cmd Option Ctrl Alt 格式化代码 Cmd Option L Ctrl Alt L 清除无效包引用 Option Contr
  • Python实现Mean Shift算法

    声明 代码的运行环境为Python3 Python3与Python2在一些细节上会有所不同 希望广大读者注意 本博客以代码为主 代码中会有详细的注释 相关文章将会发布在我的个人博客专栏 Python从入门到深度学习 欢迎大家关注 在K Me
  • 【PTA】 7-1 矩阵链相乘问题 (20 分)

    输入 5 30 35 15 5 10 20 输出 11875 代码 include
  • Python Numpy数组保存

    Numpy提供了几种数据保存的方法 以3 4数组a为例 1 a tofile filename bin 这种方法只能保存为二进制文件 且不能保存当前数据的行列信息 文件后缀不一定非要是bin 也可以为txt 但不影响保存格式 都是二进制 这
  • websocket没准备好如何解决_websocket没准备好点确定继续怎么解决,这事android? 爱问知识人...

    请采纳点赞 你可以把WebSocket看成是HTTP协议为了支持长连接所打的一个大补丁 它和HTTP有一些共性 是为了解决HTTP本身无法解决的某些问题而做出的一个改良设计 在以前HTTP协议中所谓的keep aliveconnection
  • RE整改实例——接口缝隙引起的EMC问题整改

    前言 背景 CT某一产品中的控制电路 在RE测试时候750MHz频点超过3dB 整改方法 经过近场测量分析 辐射来源于接口缝隙 经公式计算 750MHz频率引起的对应波长 0 4m 在EMC允许缝隙的长度选择中建议小于二十分之一波长 则 2
  • 只等你来!OpenAtom XuperChain 开发者夏季论坛来啦

    OpenAtom XuperChain 开源两周年之际 我们将于 6 月 25 日在上海浦东新区举办 OpenAtom XuperChain 开发者夏季论坛 特邀研究机构 企业等开源生态合作伙伴 共同探讨区块链技术发展路径和落地方向 本次论
  • solr6.6.0部署到tomcat

    准备工作 solr 6 6 0 apache tomcat 8 jdk1 8 0 131 部署 首先把solr 6 6 0 server solr webapp中的webapp目录拷贝到apache tomcat 8 5 15下的webap
  • 数据结构与算法-基础排序算法及TopK问题(Python)

    排序 基础排序算法 冒泡排序 选择排序 插入排序 归并排序 快速排序 经典问题 TopK 堆排序 快速排序 基础排序算法 如果在面试中遇到排序算法 先问清楚数据的特点 结合具体的业务场景 多和面试官交流 先陈述思路 得到面试官肯定以后再编码