leetcode 数组排序

leetcode: 排序数组

排序算法包括基础的选择排序、插入排序、交换排序;也包括快速排序,堆排序,归并排序等。其中快速排序是交换排序的升级版;堆排序是选择排序的升级版。那插入排序有没有升级版呢,也是有的,是希尔排序,但是希尔排序的思想不好理解,所以本文中不涉及希尔排序。

选择排序,插入排序,交换排序属于基础排序算法,时间复杂度是O(n * n)。快速排序和堆排序的时间复杂度是 O(nlogn)。O(logn) 这种时间复杂度跟类二分法的思想关联是很紧密的,也就是说对数据集进行处理的时候每一次都是将上一次的数据集划分成两份,然后分别对这两份做计算,快速排序和堆排序否符合这样的规律。

讨论排序算法的时候,还常常要考虑算法的稳定性。比如有一个数据序列是 {5, 10, 100, 90, 80, 100},其中第 3 个数和第 6 个数都是 100,排序之后的序列是 {5, 10, 80, 90, 100, 100},如果排序之后的两个 100,没有改变原来的先后顺序,也就是原来第三个位置的 100 排序后成为了第 5 个位置的 100,原来第 6 个位置的 100 保持位置不变,这样就是稳定的;否则,不是稳定的。

排序算法时间复杂度是否稳定
选择排序O(n * n)
插入排序O(n * n)
交换排序O(n * n)
快速排序O(nlogn)
堆排序O(nlogn)
归并排序O(nlogn)

1 选择排序

如下是选择排序的代码,典型的两层循环,时间复杂度是 O(n * n)。选择排序、插入排序、交换排序,都是两层循环,区别在于循环中的处理逻辑。 选择排序是选择一个最小的或者选择一个最大的数,然后将这个最值放到一定的位置。

class Solution {
public:vector<int> sortArray(vector<int>& nums) {int n = nums.size();for (int i = 0; i < n - 1; i++) {int min_index = i;for (int j = i + 1; j < n; j++) {if (nums[j] < nums[min_index]) {min_index = j;}}int tmp = nums[i];nums[i] = nums[min_index];nums[min_index] = tmp;}return nums;}
};

选择排序是不稳定的,如下边的数据序列:

{100, 100, 50, 20, 10}

在第一次选择的时候,最小值是 10,10 和第 1 个位置的 100 进行交换。这样原来第一个位置的 100 和第二个位置的 100 就改变了先后顺序,所以是不稳定的。

2 交换排序

交换排序又称为冒泡排序,就像下雨的时候河面上冒起的水泡一样。从前向后两两对比,如果前者较后者大,那么就进行交换,否则不交换。算法也是两层循环,和选择排序相比,除了循环中的逻辑不一样之外,两个循环的起始索引也是不一样的。内层循环的起始索引或者结束索引受外层循环的 i 影响;外层循环的起止索引往往也不是从 0 到 n - 1,而是差一个。

class Solution {
public:vector<int> sortArray(vector<int>& nums) {int n = nums.size();for (int i = 1; i < n; i++) {for (int j = 0; j < n - i; j++) {int tmp1 = nums[j];int tmp2 = nums[j + 1];if (tmp1 > tmp2) {nums[j] = tmp2;nums[j + 1] = tmp1;} }}return nums;}
};

冒泡排序是稳定的。如下数据序列,相邻的两个数据进行比较的时候,只有前者比后者大的时候才会交换;否则不交换。所以对于两个相等的数值,排序前后的先后顺序是保持不变的。

{100, 100, 50, 20, 10}

3 插入排序

插入排序是不是稳定的,关键看代码中注释的地方使用 <= 进行比较还是实用 < 进行比较,前者是稳定的;后者是不稳定的。如果可以稳定,也可以不稳定,那么我们优先选择稳定的算法。所以,插入排序是稳定的。

class Solution {
public:vector<int> sortArray(vector<int>& nums) {int n = nums.size();for (int i = 1; i < n; i++) {int data = nums[i];for (int j = 0; j < i; j++) {// 这里使用 <= 进行比较,则是稳定的// 这里使用 < 进行比较,则不是稳定的if (data <= nums[j]) {for (int k = i; k > j; k--) {nums[k] = nums[k - 1];}nums[j] = data;break; // 找到了插入的位置,则内存循环需要 break}}}return nums;}
};

插入排序也可以实现成下边的代码。插入排序就是选择一个数据向已经排序好的队列中插入数据,那么具体把这个数据插入到队列的哪个位置呢,查找位置的过程可以从前向后进行查找,也可以从后向前查找。

class Solution {
public:vector<int> sortArray(vector<int>& nums) {int n = nums.size();for (int i = 1; i < n; i++) {int data = nums[i];int j;for (j = i - 1; j >= 0; j--) {if (nums[j] > data) {nums[j + 1] = nums[j];} else {break;}}nums[j + 1] = data;}return nums;}
};

插入排序是稳定的。如下的数据序列,当将一个选择数值插入到已经排好序的队列时,这个选择的数值本来在后边,如果选择插入点的时候,只要选择的值小于当前这个值,就将选择的值插入到这个位置,这样就可以保证稳定性。

{100, 100, 50, 20, 10}

选择排序、交换排序、插入排序,都有两层循环,时间复杂度均是 O(n * n),区别在于算法的侧重点是不一样的。其实选择排序中也有交换的思想,选择一个最大值或者最小值之后,将这个最值与排好序的位置进行交换;交换排序也有选择的思想,在一遍冒泡的过程中,最终选择出来剩余数据的最大值或者最小值,这就是选择;插入排序中也有交换的思想,给选择的数据找到一个合适的位置之后,与此位置的数据进行交换。

4 快速排序

快速排序是不稳定的。如下的数据序列,首先选择第一个数 100,然后进行比较。右半段的数值比 100 小的时候进行交换,那么从右向左遍历到 1 的时候,就要交换,那么 1 会换到最左边。那么此时第 2 个位置的 1 就在第 8 个位置的 1 的后边了,所以是不稳定的。

{100, 1, 2, 10, 50, 100, 100, 1, 100, 200, 300, 500}

class Solution {
public:vector<int> sortArray(vector<int>& nums) {QuickSort(nums, 0, nums.size() - 1);return nums;}// 快速排序是递归算法void QuickSort(vector<int>& nums, int start, int end) {// 递归退出条件// start >= end 的时候,不需要进行排序了if (start >= end) {return;}// 选择 start 位置的数,作为比较和交换的对象int select_data = nums[start];int select_index = start;int start_tmp = start;int end_tmp = end;// 给选的数找到一个合适的位置,需要通过 1 次或多次循环才能找到合适的位置while(start_tmp < end_tmp) {// 从小到大排序,并且选择的是最左边的数值,那么先从右边来遍历// 如果数值比选择的数值大,那么停止遍历循环遍历// 如果数值不比选择的数值大,那么while (start_tmp < end_tmp && nums[end_tmp] > select_data) {end_tmp--;}// end_tmp 处的数值 <= 选择的数值,所以把这个数放到左边if (start_tmp < end_tmp) {nums[start_tmp] = nums[end_tmp];start_tmp++;}while (start_tmp < end_tmp && nums[start_tmp] < select_data) {start_tmp++;}if (start_tmp < end_tmp) {nums[end_tmp] = nums[start_tmp];end_tmp--;}}// 遍历完毕,start_tmp < end_tmp 不成立了// 项一个极端的情况就是,以此循环就没有执行// 那么还是把选择的数值放到 start_tmp 位置就可以了nums[start_tmp] = select_data;// 这次选择的数据的位置已经确定了// 所以下次递归计算的时候,这个位置不再参与计算了// 所以左区间的右边界是 start_tmp - 1// 右区间的左边界是 start_tmp + 1QuickSort(nums, start, start_tmp - 1);QuickSort(nums, start_tmp + 1, end);return;}
};

5 堆排序

堆排序是不稳定的。

堆排序算法-CSDN博客

6 归并排序

归并排序参考如下博客的第 2 节 链表排序

链表算法题总结-CSDN博客

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

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

相关文章

修改菜品——后端Java

s1.交互逻辑&#xff1a; 页面发送ajax请求&#xff0c;请求服务端获取分类数据&#xff0c;用于菜品分类下拉框中数据显示&#xff0c;由于修改也在add.html和服务端进行交互&#xff0c;之前添加菜品的时候该请求已经得到处理&#xff1b; 页面发送ajax请求&#xff0c;请求服…

电感十大供应商

电感品牌-电感器品牌排行榜-电感十大品牌-Maigoo品牌榜

Fences 5 激活码 - 电脑桌面整理软件

提起桌面整理&#xff0c;经典老牌工具 Fences 必有一席之地&#xff0c;Stardock 发布了最新的 Fences 5 版本。 可以将文件和图标归类放入各个栅栏分区&#xff0c;并支持文件夹展开至桌面、分区置顶、淡化隐藏图标等功能&#xff0c;能让你的桌面焕然一新&#xff0c;不再混…

自建 Docker 镜像

本文地址&#xff1a;blog.lucien.ink/archives/547 本文主要参考自&#xff1a;自建Docker 镜像/源加速的方法 1. 简介 最近 Docker Hub 被禁一事引起了不小的波动&#xff0c;在这里简单讲下在这之后应该如何访问公开的 Docker Hub。 2. Cloudflare 2.1 搭建 搭建的前提是…

(2024,扩散,DMP,提示混合,动态门控,阶段特异性,微调)通过混合提示进行扩散模型修补

Diffusion Model Patching via Mixture-of-Prompts 公和众和号&#xff1a;EDPJ&#xff08;进 Q 交流群&#xff1a;922230617 或加 VX&#xff1a;CV_EDPJ 进 V 交流群&#xff09; 目录 0 摘要 1 简介 2 相关工作 3 扩散模型修补&#xff08;DMP&#xff09; 3.1 架构…

【运维】如何在Ubuntu 22上使用Python 3.8的虚拟环境

在Ubuntu 22上使用Python 3.8的虚拟环境安装Ryu是相对简单的。以下是一步一步的指南&#xff1a; https://qq742971636.blog.csdn.net/article/details/139566151 安装Python 3.8&#xff1a; 在Ubuntu 22上&#xff0c;Python 3.8可能不是默认安装的版本。你可以使用以下命令…

Java核心知识概述

Java的核心知识涉及多个方面&#xff0c;以下是针对Java核心知识点的分点表示和归纳&#xff1a; 这些集合类提供了丰富的方法和算法&#xff0c;可以方便地对数据进行增删改查等操作。同时&#xff0c;Java还提供了迭代器和各种算法&#xff0c;如排序、搜索、过滤等&#xff…

自动化专业之半导体行业入门指南

收到一枚自动化的毕业生,还是985的。暂定为eap 方向; 先熟悉 secs/gem的通讯协议,后续跟着供应商做eap实施,慢慢接触,能够做eap的开发与copy 工作;今年是一个毕业困难季节,大环境下半导体行业还有一些用人要求,如果大家有希望去这个行业发展的话,可以参考。个人判断半…

作业40 自定义函数

求一个三位数 题目描述 求这样一个三位数&#xff0c;该三位数等于其每位数字的阶乘之和。即abc a! b! c! (n!表示n的阶乘&#xff09; 输入 无 输出 输出这个数 #include<iostream> #include<iomanip> #include<string.h> using namespace std; bool func…

用大模型理解爆火的KAN网络

上个月五一假期的时候&#xff0c;KAN突然成为了热门话题。虽然最初我并没有计划弄懂它&#xff0c;但在老板的要求下&#xff0c;我还是探索了一下。 一、KAN是什么&#xff1f; Kolmogorov-Arnold 定理是数学领域的一个里程碑&#xff0c;它揭示了多元函数能够通过一组更简…

Golang 指针使用教程

文章目录 Go语言特性Go语言指针Go指针示例Go应用场景 Go语言特性 Go函数只有 值传递Go指针 不能运算指针类型的定义与基础数据类型有关&#xff0c;即指针类型是与其指向的变量的类型相关联的。 Go语言指针 使用new函数&#xff1a; new函数用于分配内存&#xff0c;并返回一…

SpringBoot 参数验证的几种方式

文章目录 SpringBoot 参数验证1、为什么要进行参数验证2、验证方式2.1 if 语句判断2.2 Assert2.3 Validator2.3.1 引入依赖2.3.2 定义参数实体类2.3.4 定义特定异常全局拦截方法2.3.5 定义校验类进行测试2.3.6 测试 2.4 自定义验证注解2.4.1 定义自定义注解2.4.2 定义自定义验证…

Python第二语言(八、Python包)

目录 1. 什么是Python包 2. 创包步骤 2.1 new包 2.2 查看创建的包 2.3 拖动文件到包下 3. 导入包 4. 安装第三方包 4.1 什么是第三方包 4.2 安装第三方包-pip 4.3 pip网络优化 1. 什么是Python包 包下有__init__.py就是包&#xff0c;无__init__.py就是文件夹。于Ja…

嵌入式学习——Linux高级编程复习(进程)——day39

1. 进程 进程是计算机科学中的一个核心概念&#xff0c;它是操作系统进行资源分配和调度的基本单位&#xff0c;代表了一个正在执行中的程序实例。当一个程序被加载到内存并开始执行时&#xff0c;它就变成了一个进程。 1. 程序&#xff1a;存放在外存中的一段代码的集合 2. 进…

牛客 NC129 阶乘末尾0的数量【简单 基础数学 Java/Go/PHP/C++】

题目 题目链接&#xff1a; https://www.nowcoder.com/practice/aa03dff18376454c9d2e359163bf44b8 https://www.lintcode.com/problem/2 思路 Java代码 import java.util.*;public class Solution {/*** 代码中的类名、方法名、参数名已经指定&#xff0c;请勿修改&#xff…

Python 很好用的爬虫框架:Scrapy:

了解Scrapy 爬虫框架的工作流程&#xff1a; 在scrapy中&#xff0c; 具体工作流程是这样的&#xff1a; 首先第一步 当爬虫引擎<engine>启动后&#xff0c; 引擎会到 spider 中获取 start_url<起始url> 然后将其封装为一个request对象&#xff0c; 交给调度器<…

GDPU JavaWeb 大结局篇(持续更新中)

GDPUJavaWeb程序设计复习&#xff0c;习题集&#xff0c;重点知识总结&#xff0c;一篇就够了。 实验复习 JavaWeb代码复习&#xff0c;在专栏也可查阅。 课后巩固习题 1 【单选题】下列说法正确的是( D ) A、在B/S结构中,结果应用软件发生了改变,就必须通知所有的客户端重新…

Elastic Search 8.14:更快且更具成本效益的向量搜索,使用 retrievers 和重新排序提升相关性,RAG 和开发工具

作者&#xff1a;来自 Elastic Yaru Lin, Ranjana Devaji 我们致力于突破搜索开发的界限&#xff0c;并专注于为搜索构建者提供强大的工具。通过我们的最新更新&#xff0c;Elastic 对于处理以向量表示的大量数据的客户来说变得更加强大。这些增强功能保证了更快的速度、降低的…

Activity->Activity中动态添加Fragment->add和replace方式添加的区别

XML文件 Activity布局文件R.layout.activity_main <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas.android.com/apk/res/android"android:id"id/root_ll"android:orientation"v…

Linux本地搭建DataEase并发布公网远程访问进行数据分析

文章目录 前言1. 安装DataEase2. 本地访问测试3. 安装 cpolar内网穿透软件4. 配置DataEase公网访问地址5. 公网远程访问Data Ease6. 固定Data Ease公网地址 前言 DataEase 是开源的数据可视化分析工具&#xff0c;帮助用户快速分析数据并洞察业务趋势&#xff0c;从而实现业务…