成为一个合格程序员所必备的三种常见LeetCode排序算法

这篇具有很好参考价值的文章主要介绍了成为一个合格程序员所必备的三种常见LeetCode排序算法。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

排序算法是一种通过特定的算法因式将一组或多组数据按照既定模式进行重新排序的方法。通过排序,我们可以得到一个新的序列,该序列遵循一定的规则并展现出一定的规律。经过排序处理后的数据可以更方便地进行筛选和计算,从而大大提高了计算效率。因此,掌握排序算法是每个程序员的基本功之一。

今天我们将详细讲解一些与冒泡排序、快速排序和插入排序相关的leetcode真题。

冒泡排序

字如其名,冒泡排序是一种算法,它类似于水中的泡泡逐渐上升,通过逐轮比较和交换,最终使每个元素按照顺序排列。

看一下今天的题目:给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。请注意 ,必须在不复制数组的情况下原地对数组进行操作。进阶:你能尽量减少完成的操作次数吗?

示例 1:
  输入: nums = [0,1,0,3,12]
  输出: [1,3,12,0,0]

首先,这道题属于简单题目,一眼基本就可以看出来如何实现。只要遇到零就往后移动,并且冒泡排序最常见的就是双层for循环即可,然后维护两个变量随时进行数据交换。但是这种都知道的解决方案,我们不去实现。我们来实现一下进阶要求,即尽可能减少操作次数来完成数据的转换。

我们可以考虑一下,因为nums数组中不一定只有一个零,所以在操作数据时,我们将所有零都看作一个整体,只移动第一个零即可,其他的零都不用动。下面是图解:

成为一个合格程序员所必备的三种常见LeetCode排序算法

我们在这里写一下相关的Python实现代码。在这段代码中,我们使用了三元表达式的一种变种:(假,真)[条件]

from typing import List
class Solution:
    def moveZeroes(self, nums: List[int]) -> None:
        """
        Do not return anything, modify nums in-place instead.
        """
        i = 0
        j = 0
        while j < len(nums) :
            if nums[j] == 0 :
                i = (j,i)[nums[i] == 0]
            elif  nums[i] == 0 :
                nums[i] = nums[j]
                nums[j] = 0
                i = i + 1
            j = j + 1
solution = Solution()
nums = [0,1,0,3,12]
solution.moveZeroes(nums)
print(nums)

快速排序

快速排序的重要之处在于选择合适的标准数字,通过将大于和小于该数字的元素分成两部分。随后,我们不断重复这个操作。通常情况下,我倾向于使用递归方法,每次分割完后再调用以基准数字为标准的方法,直到只剩下一个元素为止。在今天的例题中,我们将探讨快速排序的应用。

给定整数数组 nums 和整数 k,请返回数组中第 k 个最大的元素。请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。你必须设计并实现时间复杂度为 O(n) 的算法解决此问题。

通常情况下,快速排序的时间复杂度是无法达到O(n)的,而且在最坏情况下可能会达到O(n2)的时间复杂度。因此,为了满足题目要求,我们需要对选择排序进行一些改进。

我们先来看下简单实现:

from typing import List
class Solution:
    def findKthLargest(self, nums: List[int], k: int) -> int:
        return sorted(nums)[len(nums) - k]
        
solution = Solution()
nums = [3,2,3,1,2,4,5,5,6]
k = 4
print(solution.findKthLargest(nums, k))        

然而,这样的实现肯定无法满足O(n)的时间复杂度要求。因此,我们需要进行进一步优化。如果我第一反应是降低时间复杂度,我可能会考虑牺牲空间复杂度,然后逐步进行优化。根据这个,我写出来了递归。

from typing import List

class Solution:
    def findKthLargest(self, nums: List[int], k: int) -> int:
        def quickSelect(nums,k) -> int:
            # 选择一个作为基准
            result = nums[0]
            # 将数组分为三部分,大于、等于、小于
            big ,equal,small = [],[],[]
            # for循环不要排序,一进行排序就会增加时间复杂度。
            for num in nums:
                if num > result:
                    big.append(num)
                elif num < result:
                    small.append(num)
                else :
                    equal.append(num)
            # 说明在big中
            if k <= len(big):
                return quickSelect(big,k)
            if k > len(big) + len(equal):
                return quickSelect(small,k - len(big) - len(equal))
            return result

        return quickSelect(nums,k)

solution = Solution()
nums = [3,2,3,1,2,4,5,5,6]
k = 4
print(solution.findKthLargest(nums, k))

为了更加方便大家理解,我还特意制作了一个简单的图例,以便于更直观地说明。

成为一个合格程序员所必备的三种常见LeetCode排序算法

插入排序

插入排序(Insertion Sort)是一种简单直观的排序算法。其基本思想是将待排序序列分为已排序和未排序两部分。每次从未排序部分取出一个元素,将其插入到已排序部分的合适位置,直到所有元素都被插入到已排序部分为止。这种排序方法相对其他复杂的排序算法而言,实现简单、容易理解,适用于小规模数据的排序。

我们来看下正题:

给你一个整数数组 nums,请你将该数组升序排列。

输入:nums = [5,1,1,2,0,0]
输出:[0,0,1,1,2,5]

我们先来简单实现一个插入排序:

from typing import List

class Solution:

    def insertSort(self,index: int,nums: List[int]):
        temp = nums[index]
        while index > 0 and temp < nums[index-1] :
            nums[index] =  nums[index-1]
            index = index - 1
        nums[index] = temp

    def sortArray(self, nums: List[int]) -> List[int]:
        for i in range(1,len(nums)):
            self.insertSort(i,nums)
        return nums
   
insert = Solution();
nums = [5,1,1,2,0,0]
print(insert.sortArray(nums))

为了更好地说明,我简单地绘制了一个图例。请注意,数字的顺序应根据实际情况而定,而不是根据图中的显示顺序来确定。图中主要展示了交换和比较的过程。

成为一个合格程序员所必备的三种常见LeetCode排序算法

然而,插入排序明显不是最优的算法,因为它的运行时间超过了限制。主要原因是插入排序的时间复杂度仍然偏高。那么,我来提出一种简单的优化方法,主要是减少比较和交换操作的消耗。我们知道,如果数组的前面部分已经是有序的,那么我们可以首先考虑使用二分查找来减少比较次数。我们来实现一下:

from typing import List

class Solution:

    def findIndex(self,begin:int, end: int,temp: int,nums: List[int]):
        if begin <= end :
            return begin
        mid = (begin + end ) / 2
        if nums[mid] > temp:
            findIndex(begin,mid,temp,nums)
        else :
            findIndex(mid,end,temp,nums)   

    def insertSort2(self,index: int,nums: List[int]):
        temp = nums[index]
        small = self.findIndex(0,index,temp,nums)
        while index > small and temp < nums[index-1] :
            nums[index] =  nums[index-1]
            index = index - 1
        nums[index] = temp

    def sortArray(self, nums: List[int]) -> List[int]:
        for i in range(1,len(nums)):
            self.insertSort2(i,nums)
        return nums
   
insert = Solution();
nums = [5,1,1,2,0,0]
print(insert.sortArray(nums))

本来我觉得这次的任务应该能够顺利通过,但是却没能满足时间限制要求,结果还是超时了。接下来,为了优化交换次数,我需要考虑使用插入排序的高级变体——希尔排序。

希尔排序

希尔排序是一种优化的插入排序算法,它的重点是通过增加间隔来减少元素之间的比较次数。相比于传统的插入排序一次比较一个元素,希尔排序通过间隔的设定,可以一次比较多个元素。为了更好地理解这个过程,我简单地画了一张图。

成为一个合格程序员所必备的三种常见LeetCode排序算法

如果采用之前的插入排序算法,将数字0移动到前面将需要进行多次比较和交换操作,这将导致效率较低。而如果使用希尔排序并增加间隔,可以避免对中间数字进行比较和交换操作,从而有效减少了所需的比较和交换次数。

我们来简单实现一下算法:

from typing import List

class Solution:

    def insertSort3(self,index: int,nums: List[int],gap: int):
        temp = nums[index]
        while index-gap >= 0 and temp < nums[index-gap] :
            nums[index] =  nums[index-gap]
            index = index - gap
        nums[index] = temp

    def sortArray(self, nums: List[int]) -> List[int]:
        gap = len(nums) // 2
        while gap > 1 :
            for i in range(gap,len(nums)):
                self.insertSort3(i,nums,gap)
            gap = gap // 2
        return nums
insert = Solution();
nums = [5,1,1,2,0,0]
print(insert.sortArray(nums))

终于通过了这道题目,从代码实现上来看,与插入排序相比,它多了一些变量,但仍然很容易理解。然而,由于数组前面不再是绝对有序的,我们需要放弃使用二分查找。文章来源地址https://www.toymoban.com/news/detail-797179.html

到了这里,关于成为一个合格程序员所必备的三种常见LeetCode排序算法的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 如何成为一名全职创作者——程序员篇

    哈喽大家好,我是咸鱼 今天跟大家分享一篇文章,这篇文章的作者 Gergely Orosz 是一名程序员,他从 Uber 辞职以后,就当起了全职创作者 他通过写文章、卖课程、做视频等谋生,今天这篇文章是他对这种商业模式的思考,我把它主要部分翻译了出来(想要看全文的原文链接在

    2024年02月08日
    浏览(44)
  • 程序员必备技能之调试

    目录 前言 本期内容介绍 一、什么是Bug? 二、调试以及调试的重要性 2.1什么是调试? 2.2调试的基本步骤 ​三、Debug和Release介绍 Debug和Release 四、windows环境下的调试介绍 4.1调试环境 4.2一些调试常用的快捷键 4.3调试时查看当前程序的信息 a、查看临时变量的值 b、查看程序的

    2024年02月10日
    浏览(65)
  • 程序员必备的面试技巧

    “程序员必备的面试技巧,就像是编写一段完美的代码一样重要。在面试战场上,我们需要像忍者一样灵活,像侦探一样聪明,还要像无敌铁金刚一样坚定。只有掌握了这些技巧,我们才能在面试的舞台上闪耀光芒,成为那个令HR们心动的程序猿!” 提醒:在发布作品前,请

    2024年01月21日
    浏览(51)
  • 爆火的 ChatGPT,会成为程序员的 “就业杀手” 吗?

    即使你过去从不关心科技领域,最近应该都被一个叫 “ ChatGPT ” 的人工智能刷屏。 与上一任 “全球网红” 元宇宙不同,这位新晋的 “全能网友” 来势汹汹,互联网上盛传它将要抢走一大批人的饭碗。 有人认为,随着 ChatGPT 技术的成熟和应用,底层程序员将面临失业的风

    2023年04月25日
    浏览(42)
  • 程序员必备技能:一键创建windows 服务

    使用windows开发或者使用windows服务器的朋,应该经常会遇到有些程序要开机启动,或者有些服务要持续执行。 这样最稳定可靠的,就是把程序创建为windows服务。 以下bat脚本,仅供参考。 把以上代码复制到记事本,保存为.bat文件。然后管理员身份运行即可创建服务。 运行完

    2024年02月19日
    浏览(49)
  • C++程序员必备的面试技巧

      “程序员必备的面试技巧,就像是编写一段完美的代码一样重要。在面试战场上,我们需要像忍者一样灵活,像侦探一样聪明,还要像无敌铁金刚一样坚定。只有掌握了这些技巧,我们才能在面试的舞台上闪耀光芒,成为那个令HR们心动的程序猿!” 在准备C++程序员面试时

    2024年02月01日
    浏览(50)
  • C语言技巧 ----------调试----------程序员必备技能

      🎂        ✨✨✨✨✨✨🍧🍧🍧🍧🍧🍧🍧🎂    🎂      作者介绍:                              🎂🎂        🎂 🎉🎉🎉🎉🎉🎉🎉              🎂           🎂作者id:老秦包你会,         🎂 简单介绍:🎂🎂🎂🎂🎂🎂🎂🎂🎂🎂🎂🎂🎂🎂

    2024年02月13日
    浏览(52)
  • 程序员必备之——代码托管工具 git

    目录 一、git的安装及本地配置 1.1、git介绍 1.2、git本地安装及配置 1.3、git远程仓库 二、git的命令及使用 2.1、基础命令 三、git的分支 3.1、常用命令 3.2、执行效果图 3.3、合并时有冲突该怎么办? 3.4、解决冲突 3.5、git分支图解 四、连接远程仓库 4.1、在gitee新建远程仓库 4.2、

    2024年02月08日
    浏览(51)
  • 程序员必备的10张流程图

    随着互联网的发展,现在有越来越多的人想成为程序员。 如果你想成为程序员你可以先问自己这几个问题? •你是一个逻辑和抽象思维能力比较强的人吗? •你是否愿意不断地去学习那些新的东西,并且在大多数时间内你都需要去自学。 •当你遇到一些问题和困难的时候,

    2024年02月07日
    浏览(51)
  • 【必备】计算机行业、程序员必备的工具和软件 拒绝标题党

    博主并不是广告推销 只是分享自己接触的好用的软件和工具,所以一切从简 不会用长篇大论去介绍优点。 博主自己的笔记本是在用来办公的,所以不会去下载一切乱七八糟的东西,这些软件或工具 要么有自己的官方下载安装渠道 要么是开源的。 火绒 一个轻量的杀毒软件,

    2023年04月24日
    浏览(72)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包