【Python 算法零基础 4.排序 ② 冒泡排序】

news2025/5/24 1:34:26

目录

一、引言

二、算法思想

三、时间复杂度和空间复杂度

1.时间复杂度

2.空间复杂度

四、冒泡排序的优缺点

1.算法的优点

2.算法的缺点

五、实战练习

88. 合并两个有序数组

算法与思路

① 合并数组

② 冒泡排序

2148. 元素计数

算法与思路

① 排序

② 初始化计数器

③ 遍历数组

④ 返回结果

1046. 最后一块石头的重量

算法与思路 

① 冒泡排序

② 石头碰撞模拟


我走的很慢

从不是优秀的人

但是没关系

我很少停下

脆弱会给我新力量

                     —— 25.5.19

选择排序回顾:

① 初始化从未排序序列开始,初始时整个数组都是未排序的。

② 寻找最小值遍历未排序部分的所有元素,找到其中的最小值。使用变量min_idx记录最小值的索引,初始时假设当前未排序部分的第一个元素是最小的。

③ 交换元素:将找到的最小值与未排序部分的第一个元素交换位置。此时,未排序部分的第一个元素成为已排序序列的一部分。

④ 重复步骤 2-3缩小未排序部分的范围(从下一个元素开始),重复寻找最小值并交换的过程,直到整个数组排序完成。

def selection_sort(arr):
    for i in range(len(arr)):
        min_idx = i
        for j in range(i+1, len(arr)):
            if arr[j] < arr[min_idx]:
                arr[i], arr[min_idx] = arr[min_idx], arr[i]
    return arr

一、引言

        冒泡排序(Bubble Sort)是一种简单的排序算法,通过多次比较和交换相邻的元素,将列表(数组)中的元素按照升序或降序排列


二、算法思想

        冒泡排序的基本思想:每次遍历数组,比较相邻的两个元素,如果它们的顺序错误,就将它们交换,直到数组中的所有元素都被遍历过

        具体的算法步骤如下:

                ① 遍历数组的第一个元素到最后一个元素。

                ② 对每一个元素,与其后一个元素进行比较。

                ③ 如果顺序错误,就将它们交换。

                ④ 重复上述步骤,直到数组中的所有元素都被遍历过至少一次。


三、时间复杂度和空间复杂度

1.时间复杂度

        我们假设【比较】和【交换】的时间复杂度为O(1)

        【冒泡排序】中有两个嵌套循环

                外循环正好运行n - 1次迭代。但内部循环运行变得越来越短:

                当i = 0,内层循环n - 1次【比较】操作。

                当i = 1,内层循环n - 2次【比较】操作。

                当i = 2,内层循环n - 3次【比较】操作。

                当i = n - 2,内层循环1次【比较】操作。

                当i = n - 1,内层循环0次【比较】操作。

因此,总「比较」次数如下:(n - 1) + (n - 2) + ... + 1 + 0 = n (n - 1) / 2,总的时间复杂度为:O(n ^ 2)


2.空间复杂度

        由于算法在执行过程中,只有【交换】变量时候采用了临时变量的方式,而其它没有采用任何的额外空间,所以空间复杂度为O(1)。


四、冒泡排序的优缺点

1.算法的优点

① 简单易懂:冒泡排序的算法思想非常简单,容易理解和实现。

② 稳定排序:冒泡排序是一种稳定的排序算法,即在排序过程中不会改变相同元素的相对顺序。

2.算法的缺点

① 效率较低:由于需要进行多次比较和交换,冒泡排序在处理大规模数据时效率较低。

② 排序速度慢:对于大型数组,冒泡排序的时间复杂度较高,导致排序速度较慢。


五、实战练习

88. 合并两个有序数组

给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2,另有两个整数 m 和 n ,分别表示 nums1 和 nums2 中的元素数目。

请你 合并 nums2 到 nums1 中,使合并后的数组同样按 非递减顺序 排列。

注意:最终,合并后数组不应由函数返回,而是存储在数组 nums1 中。为了应对这种情况,nums1 的初始长度为 m + n,其中前 m 个元素表示应合并的元素,后 n 个元素为 0 ,应忽略。nums2 的长度为 n 。

示例 1:

输入:nums1 = [1,2,3,0,0,0], m = 3, nums2 = [2,5,6], n = 3
输出:[1,2,2,3,5,6]
解释:需要合并 [1,2,3] 和 [2,5,6] 。
合并结果是 [1,2,2,3,5,6] ,其中斜体加粗标注的为 nums1 中的元素。

示例 2:

输入:nums1 = [1], m = 1, nums2 = [], n = 0
输出:[1]
解释:需要合并 [1] 和 [] 。
合并结果是 [1] 。

示例 3:

输入:nums1 = [0], m = 0, nums2 = [1], n = 1
输出:[1]
解释:需要合并的数组是 [] 和 [1] 。
合并结果是 [1] 。
注意,因为 m = 0 ,所以 nums1 中没有元素。nums1 中仅存的 0 仅仅是为了确保合并结果可以顺利存放到 nums1 中。

提示:

  • nums1.length == m + n
  • nums2.length == n
  • 0 <= m, n <= 200
  • 1 <= m + n <= 200
  • -109 <= nums1[i], nums2[j] <= 109

算法与思路

① 合并数组

将 nums2 的前 n 个元素依次复制到 nums1 的后 n 个位置(从索引 m 开始)。

② 冒泡排序

使用两层循环对合并后的 nums1 进行升序排序:

        外层循环遍历每个元素(索引 i 从 0 到 mn-1)。

        内层循环比较 i 之后的所有元素(索引 j 从 i+1 到 mn-1)。

若发现 nums1[i] > nums1[j],则交换两者位置。

class Solution:
    def merge(self, nums1: List[int], m: int, nums2: List[int], n: int) -> None:
        """
        Do not return anything, modify nums1 in-place instead.
        """
        for i in range(n):
            nums1[m + i] = nums2[i]
        mn = len(nums1)
        for i in range(mn):
            for j in range(mn - i -1):
                if nums1[j] > nums1[j + 1]:
                    nums1[j], nums1[j + 1] = nums1[j + 1], nums1[j] 


2148. 元素计数

给你一个整数数组 nums ,统计并返回在 nums 中同时至少具有一个严格较小元素和一个严格较大元素的元素数目。

示例 1:

输入:nums = [11,7,2,15]
输出:2
解释:元素 7 :严格较小元素是元素 2 ,严格较大元素是元素 11 。
元素 11 :严格较小元素是元素 7 ,严格较大元素是元素 15 。
总计有 2 个元素都满足在 nums 中同时存在一个严格较小元素和一个严格较大元素。

示例 2:

输入:nums = [-3,3,3,90]
输出:2
解释:元素 3 :严格较小元素是元素 -3 ,严格较大元素是元素 90 。
由于有两个元素的值为 3 ,总计有 2 个元素都满足在 nums 中同时存在一个严格较小元素和一个严格较大元素。

提示:

  • 1 <= nums.length <= 100
  • -105 <= nums[i] <= 105

算法与思路

① 排序

调用 bubbleSort 对数组进行升序排序。

② 初始化计数器

count = 0

③ 遍历数组

对于每个元素 x,检查其是否不等于数组的第一个元素(最小值)和最后一个元素(最大值)。若是,则 count += 1

④ 返回结果

最终计数器的值。

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

    def countElements(self, nums: List[int]) -> int:
        self.bubbleSort(nums)
        count = 0
        for x in nums:
            if x != nums[0] and x != nums[-1]:
                count += 1
        return count


1046. 最后一块石头的重量

有一堆石头,每块石头的重量都是正整数。

每一回合,从中选出两块 最重的 石头,然后将它们一起粉碎。假设石头的重量分别为 x 和 y,且 x <= y。那么粉碎的可能结果如下:

  • 如果 x == y,那么两块石头都会被完全粉碎;
  • 如果 x != y,那么重量为 x 的石头将会完全粉碎,而重量为 y 的石头新重量为 y-x

最后,最多只会剩下一块石头。返回此石头的重量。如果没有石头剩下,就返回 0

示例:

输入:[2,7,4,1,8,1]
输出:1
解释:
先选出 7 和 8,得到 1,所以数组转换为 [2,4,1,1,1],
再选出 2 和 4,得到 2,所以数组转换为 [2,1,1,1],
接着是 2 和 1,得到 1,所以数组转换为 [1,1,1],
最后选出 1 和 1,得到 0,最终数组转换为 [1],这就是最后剩下那块石头的重量。

提示:

  • 1 <= stones.length <= 30
  • 1 <= stones[i] <= 1000

算法与思路 

① 冒泡排序

每轮固定一个位置:通过外层循环 i 控制当前处理的位置,从 0 到 n-1

比较后续所有元素:内层循环 j 从 i+1 开始,将 nums[i] 与后续所有元素比较。

交换较大值:若 nums[i] > nums[j],则交换两者,确保 i 位置的元素是当前未排序部分的最小值。

② 石头碰撞模拟

初始化:获取石头数组长度 n,作为循环终止条件。

循环条件:当 n > 1 时,持续处理(确保至少有两块石头可碰撞)。

排序:每次循环调用 bubbleSort 对数组升序排序,使最重的石头位于末尾

碰撞操作:取出最重的两块石头 stones[-1] 和 stones[-2],计算差值 v

更新数组

        移除碰撞的石头:通过两次 pop() 移除末尾两个元素,n 减 2。

        添加新石头:若 v != 0(两块石头重量不同)或 n == 0(碰撞后无剩余石头),将 v 加入数组,n 加 1。

返回结果:循环结束后,若 n == 1,返回剩余石头 stones[0]

class Solution:
    def bubble_sort(arr):
        """
        冒泡排序的标准实现
        """
        n = len(arr)
        # 遍历所有数组元素
        for i in range(n):
            # 最后i个元素已经就位,无需再比较
            for j in range(0, n-i-1):
                # 遍历数组从0到n-i-1
                # 交换元素如果当前元素大于下一个元素
                if arr[j] > arr[j+1]:
                    arr[j], arr[j+1] = arr[j+1], arr[j]
        return arr

    def lastStoneWeight(self, stones: List[int]) -> int:
        n = len(stones)
        while n > 1:
            self.bubbleSort(stones)
            v = stones[-1] - stones[-2]
            n -= 2
            stones.pop()
            stones.pop()
            if v != 0 or n == 0:
                stones.append(v)
                n += 1
        return stones[0]

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2384263.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Python:操作Excel设置行高和列宽

Python 操作 Excel:轻松设置行高与列宽 📊✨ 在处理 Excel 表格时,除了正确展示数据本身,合理设置行高与列宽也是提升可读性和专业度的关键因素。本文将带你了解如何使用 Python 的 openpyxl 库,优雅地控制 Excel 表格的排版布局,实现行高、列宽的灵活设置与自动适配! …

docker-volume-backup 备份 ragflow volumes

自定义项目名称 这里我自定义了 ragflow 项目的名称&#xff0c;修改 .env&#xff0c;添加环境配置 # 自定义项目名称 COMPOSE_PROJECT_NAMEragflow创建备份脚本配置文件 在 ragflow/docker 目录下创建文件 docker-compose-backup.yml version: 3services:backup:image: o…

Axure设计数字乡村可视化大屏:从布局到交互的实战经验分享

乡村治理正从传统模式向“数据驱动”转型。数字乡村可视化大屏作为数据展示的核心载体&#xff0c;不仅能直观呈现乡村发展全貌&#xff0c;还能为决策提供科学依据。本文以Axure为工具&#xff0c;结合实际案例&#xff0c;分享如何从零设计一个功能完备、交互流畅的数字乡村大…

算法第26天 | 贪心算法、455.分发饼干、376. 摆动序列、 53. 最大子序和

弹性算法理论基础 想清楚 局部最优 是什么&#xff0c;如果可以推导出全局最优&#xff0c;那就是正确的贪心算法 455. 分发饼干 题目 思路与解法 class Solution:def findContentChildren(self, g: List[int], s: List[int]) -> int:res 0i 0j 0g.sort()s.sort()whi…

PDF处理控件Aspose.PDF教程:以编程方式将 PDF 导出为 JPG

在本节中&#xff0c;我们将探讨如何使用 Aspose.PDF 库将 PDF 文档转换为 JPG 图像。Aspose.PDF 是一个功能强大且用途广泛的库&#xff0c;专为需要以编程方式处理 PDF 文件的开发人员而设计。它提供了丰富的功能&#xff0c;可用于跨多个平台创建、编辑和转换 PDF 文档。其主…

AI大模型应用之评测篇

在看到公司对于AI 工程师 的岗位要求 &#xff1a;“能够熟练使用各种自动化评测工具与方法&#xff0c;对AI 模型的输出进行有效评估” 时&#xff0c;其实比较疑惑&#xff0c;这个是对大模型能力例如像Deepseek ,GPT-4 ,千问&#xff0c;LLAMA这些模型的能力评测&#xff0c…

力扣小题, 力扣113.路径总和II力扣.111二叉树的最小深度 力扣.221最大正方形力扣5.最长回文子串更加优秀的算法:中心扩展算法

目录 力扣113.路径总和II 力扣.111二叉树的最小深度 力扣.221最大正方形 力扣5.最长回文子串 更加优秀的算法:中心扩展算法 力扣113.路径总和II 这道题&#xff0c;让我明白回溯了到底啥意思 之前我找的时候&#xff0c;我一直在想&#xff0c;如果可以&#xff0c;请你对比…

el-form elform 对齐方式调整

如下页面表单&#xff0c;展示后就很丑。 页面表单&#xff0c;有时候我们想着最左侧的应该合理整齐的左对齐&#xff0c;右侧的表单都是右对齐&#xff0c;这样页面看起来会整洁很多。 <el-form class"w-100 a_form" style"padding: 0 15px 0px 15px"…

JESD204 ip核使用与例程分析(二)

JESD204 ip核使用与例程分析(二) JESD204时钟方案专用差分时钟对例程分析jesd204_0_transport_layer_demapperjesd204_0_sig_chkjesd204_0_clockingjesd204_0 ip核port寄存器AXI-LITE寄存器配置jesd204_phy ip核JESD204时钟方案 图3-1所示为最通用、灵活的时钟解决方案。在图…

50天50个小项目 (Vue3 + Tailwindcss V4) ✨ | Blurry Loading (毛玻璃加载)

&#x1f4c5; 我们继续 50 个小项目挑战&#xff01;—— Blurry Loading 组件 仓库地址&#xff1a;https://github.com/SunACong/50-vue-projects 项目预览地址&#xff1a;https://50-vue-projects.vercel.app/ ✨ 组件目标 实现一个加载进度条&#xff0c;随着加载进度的…

演示:【WPF-WinCC3D】 3D工业组态监控平台源代码

一、目的&#xff1a;分享一个应用WPF 3D开发的3D工业组态监控平台源代码 二、功能介绍 WPF-WinCC3D是基于 WPF 3D研发的工业组态软件&#xff0c;提供将近200个预置工业模型&#xff08;机械手臂、科幻零部件、熔炼生产线、机加生产线、管道等&#xff09;&#xff0c;支持组态…

【PostgreSQL数据分析实战:从数据清洗到可视化全流程】1.4 数据库与表的基本操作(DDL/DML语句)

&#x1f449; 点击关注不迷路 &#x1f449; 点击关注不迷路 &#x1f449; 点击关注不迷路 文章大纲 1.4 数据库与表的基本操作&#xff08;DDL/DML语句&#xff09;1.4.1 数据库生命周期管理&#xff08;DDL核心&#xff09;1.4.1.1 创建数据库&#xff08;CREATE DATABASE&…

如何在电脑上登录多个抖音账号?多开不同IP技巧分解

随着短视频的爆发式增长&#xff0c;抖音已经成为许多人生活和工作的必备平台。不论是个人内容创作者、品牌商家&#xff0c;还是营销人员&#xff0c;都可能需要管理多个抖音账号。如何在电脑上同时登录多个抖音账号&#xff0c;提升工作效率&#xff0c;避免频繁切换账号的麻…

【东枫科技】usrp rfnoc 开发环境搭建

作者 太原市东枫电子科技有限公司 &#xff0c;代理销售 USRP&#xff0c;Nvidia&#xff0c;等产品与技术支持&#xff0c;培训服务。 环境 Ubuntu 20.04 依赖包 sudo apt-get updatesudo apt-get install autoconf automake build-essential ccache cmake cpufrequtils …

【JAVA资料,C#资料,人工智能资料,Python资料】全网最全编程学习文档合集,从入门到全栈,保姆级整理!

文章目录 前言一、编程学习前的准备​1.1 明确学习目标​1.2 评估自身基础​ 二、编程语言的选择​2.1 热门编程语言介绍​2.2 如何根据目标选择语言​ 三、编程基础学习​3.1 变量与数据类型​3.2 控制结构​3.3 函数​ 四、面向对象编程&#xff08;OOP&#xff09;​4.1 OOP…

[IMX] 05.串口 - UART

目录 1.通信格式 2.电平标准 3.IMX UART 模块 4.时钟寄存器 - CCM_CSCDR1 5.控制寄存器 5.1.UART_UCR1 5.2.UART_UCR2 5.3.UART_UCR3 6.状态寄存器 6.1.UART_USR1 6.2.UART_USR2 7.FIFO 控制寄存器 - UART_UFCR 8.波特率寄存器 8.1.分母 - UART_UBIR 8.2.分子 -…

使用Tkinter写一个发送kafka消息的工具

文章目录 背景工具界面展示功能代码讲解运行环境创建GUI程序搭建前端样式编写功能实现代码 背景 公司是做AR实景产品的&#xff0c;近几年无人机特别的火&#xff0c;一来公司比较关注低空经济这个新型领域&#xff0c;二来很多政企、事业单位都采购了无人机用于日常工作。那么…

MongoDB 与 EF Core 深度整合实战:打造结构清晰的 Web API 应用

题纲 MongoDB 字符串连接 URIC# 连接字符串实例 实现一个电影信息查询 demo创建项目创建实体实现 DbContext 上下文仓储实现服务实现控制器实现服务注册快照注入数据库连接配置1. 注册配置类2. 注入 IOptionsSnapshot<MongoDbSettings>3. 配置文件 appsettings.json 示例…

重写B站(网页、后端、小程序)

1. 网页端 1.1 框架 Vue ElementUI axios 1.2 框架搭建步骤 搭建Vue 1.3 配置文件 main.js import {createApp} from vue import ElementUi from element-plus import element-plus/dist/index.css; import axios from "axios"; import router from…

文档债务拖累交付速度?5大优化策略文档自动化

开发者在追求开发速度的过程中&#xff0c;往往会忽视文档的编写&#xff0c;如省略设计文档、代码注释或API文档等。这种做法往往导致在后期调试阶段需要花费三倍以上的时间来理解代码逻辑&#xff0c;进而形成所谓的文档债务&#xff0c;严重拖累交付速度并造成资源浪费。而积…