AcWing算法基础课-785快速排序-Java题解

heweilai-bolg-title-image-of-the-article

大家好,我是何未来,本篇文章给大家讲解《AcWing算法基础课》785 题——快速排序。这篇文章介绍了使用快速排序算法对整数数列进行排序的方法,包括选择基准元素、分区操作和递归排序子数组。通过详细的步骤和示例,解释了快速排序的过程及其非稳定性特征,并提供了相应的 Java 代码实现。

文章目录

  • ❓题目描述
  • 💡算法思路
  • ✅Java代码
  • 🔗参考

❓题目描述

给定你一个长度为 n 的整数数列。

请你使用快速排序对这个数列按照从小到大进行排序。

并将排好序的数列按顺序输出。

输入格式

输入共两行,第一行包含整数 n。

第二行包含 n 个整数(所有整数均在 1∼10^9 范围内),表示整个数列。

输出格式

输出共一行,包含 n 个整数,表示排好序的数列。

数据范围

1≤n≤100000

输入样例:

5
3 1 2 4 5

输出样例:

1 2 3 4 5

💡算法思路

  1. 选择基准元素:从数组中选择一个元素作为基准。这里我们选择的是中间位置的元素。
  2. 分区操作:重新排列数组,将所有比基准值小的元素摆放在基准前面,所有比基准值大的元素摆在基准的后面(相同的数可以到任一边)。在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区操作。
  3. 递归排序子数组:递归地将小于基准值元素的子数列和大于基准值元素的子数列排序。

具体实现步骤如下:

  • 首先检查数组的起始索引l是否大于或等于结束索引r,如果是,则直接返回,因为这意味着数组已经是有序的或者是空数组。
  • 初始化两个指针ij,分别指向数组的起始位置的前一个位置和结束位置的后一个位置。选择数组的中间元素作为基准元素x
  • 使用两个指针ij从数组的两端向中间移动,直到i找到一个大于或等于基准的元素,j找到一个小于或等于基准的元素。如果i仍然小于j,则交换这两个元素。
  • 重复上述过程,直到i不再小于j
  • 递归地对基准元素左侧和右侧的子数组进行快速排序。

时间复杂度:O(n log n)
空间复杂度:O(n)
快速排序是非稳定排序:快速排序的分区过程中,当遇到与基准元素相等的元素时,通常会停止移动指针(在某些实现中,指针会继续移动),这可能导致相同元素的相对顺序被改变。例如,如果数组中有多个相同的元素,分区操作可能会将这些元素分散到基准的两侧,从而改变它们的相对顺序。

稳定排序的定义是:在排序过程中,具有相同键值的元素在排序前后的相对位置保持不变。然而,快速排序的分区操作可能会改变相同元素的相对顺序。

接下来,我给大家举个具体的例子来说明为什么快速排序是非稳定排序。

假设我们有一个包含学生信息的数组,每个学生由他们的姓名和成绩组成。我们希望按照成绩对学生进行排序。初始数组如下:

[ ("何未来", 85), ("乔布斯", 75), ("牛顿", 85), ("图灵", 75) ]

选择基准元素 ("牛顿", 85),进行第一次分区操作:

  1. 初始指针位置:i = -1j = 4
  2. 移动 i 直到找到大于或等于基准的元素:i 停在 ("何未来", 85)
  3. 移动 j 直到找到小于或等于基准的元素:j 停在 ("图灵", 75)
  4. 交换 ij 指向的元素:
[ ("图灵", 75), ("乔布斯", 75), ("牛顿", 85), ("何未来", 85) ]

第一次分区结束,基准元素 ("牛顿", 85) 的位置已经确定。现在我们有两个子数组:

  • 左子数组:[ ("图灵", 75), ("乔布斯", 75) ]
  • 右子数组:[ ("何未来", 85) ]

我们先对左子数组进行递归排序:

选择基准元素 ("乔布斯", 75),进行第二次分区操作:

  1. 初始指针位置:i = -1j = 2
  2. 移动 i 直到找到大于或等于基准的元素:i 停在 ("图灵", 75)
  3. 移动 j 直到找到小于或等于基准的元素:j 停在 ("乔布斯", 75)
  4. 交换 ij 指向的元素:
[ ("乔布斯", 75), ("图灵", 75) ]

第二次分区结束,基准元素 ("乔布斯", 75) 的位置已经确定。现在我们有两个子数组:

  • 左子数组:[ ](空数组)
  • 右子数组:[ ("图灵", 75) ]

由于左子数组为空,右子数组只有一个元素,这两个子数组都已经是有序的。

接下来对右子数组进行递归排序:

右子数组 [ ("何未来", 85) ] 只有一个元素,已经是有序的。

最终排序结果:

[ ("乔布斯", 75), ("图灵", 75), ("牛顿", 85), ("何未来", 85) ]

通过这个过程,我们可以看到,初始数组中相同成绩的学生 ("何未来", 85)("牛顿", 85) 的相对顺序在排序后发生了变化,从 ("何未来", 85) 在前变成了 ("牛顿", 85) 在前。这就是快速排序不稳定性的体现。

✅Java代码

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StreamTokenizer;public class Aw785 {// 创建一个StreamTokenizer用于读取输入static StreamTokenizer in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));// 读取下一个整数的方法static int nextInt() throws IOException {in.nextToken();return (int) in.nval;}static int n; // 存储数组的大小static int[] nums = new int[100000 + 10]; // 存储输入的数组,预留一些额外的空间public static void main(String[] args) throws IOException {n = nextInt(); // 读取数组的大小for (int i = 0; i < n; i++) {nums[i] = nextInt(); // 读取数组的每个元素}quickSort(0, n - 1, nums); // 调用快速排序方法对数组进行排序for (int i = 0; i < n; i++) {System.out.print(nums[i] + " "); // 输出排序后的数组}}// 快速排序方法,参数为数组的起始和结束索引,以及数组本身static void quickSort(int l, int r, int[] a) {if (l >= r) { // 如果起始索引大于或等于结束索引,则直接返回return;}int i = l - 1, j = r + 1, x = a[l + r >> 1]; // 初始化指针i, j和基准元素x,以中间元素作为基准元素while (i < j) { // 当i小于j时,执行循环do {i++; // i指针向右移动,直到找到一个大于或等于x的元素} while (a[i] < x);do {j--; // j指针向左移动,直到找到一个小于或等于x的元素} while (a[j] > x);if (i < j) { // 如果i仍然小于j,交换这两个元素int tmp = a[i];a[i] = a[j];a[j] = tmp;}}quickSort(l, j, a); // 递归排序左半部分quickSort(j + 1, r, a); // 递归排序右半部分}}

🔗参考

  • https://www.acwing.com/problem/content/787/
  • https://www.hello-algo.com/chapter_sorting/quick_sort/

作者:程序员何未来-heweilai.com


🔍推荐阅读

  1. 【七夕节实践】把爱心代码放在自己的网站上是什么体验?
  2. 塑造你的技术名片:写给程序员的个人品牌建设指南
  3. 博客赚钱全攻略:从新手到专家的变现之路

欢迎关注我的博客:@程序员何未来,持续为你输出有价值的技术文章~
你们的点赞👍 收藏⭐ 留言🗨️ 关注✅
是我持续创作,输出优质内容的最大动力!谢谢!

文章关键词:算法,计算机算法,算法题解,算法竞赛,Java,数据结构,AcWing算法基础课

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

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

相关文章

MySQL之数据库基础

目录 一、数据库 1、基本概念 2、常见的数据库 3、MySQL数据库 连接MySQL服务器 数据逻辑存储 二、数据库和表的本质 三、SQL语句 四、服务器&#xff0c;数据库&#xff0c;表的关系 五、存储引擎 查看存储引擎 一、数据库 1、基本概念 一般来说&#xff0c;数据库…

es映射配置(_mapping)

文章目录 1、创建映射字段2、查看映射关系 1、创建映射字段 PUT /索引库名/_mapping {"properties": {"字段名": {"type": "类型","index": true&#xff0c;"store": true&#xff0c;"analyzer": &q…

视频结构化从入门到精通——视频结构化主要技术介绍

视频结构化主要技术 1 视频接入 “视频接入”是视频结构化管道的起点&#xff08;SRC Point&#xff09;视频接入是视频结构化处理的第一步&#xff0c;它涉及将视频数据从各种采集源获取到系统中进行进一步处理。视频接入的质量和稳定性对后续的数据处理、分析和应用至关重要…

多参数遥测终端科技守护水电站生态流量下泄

随着我国水电事业的蓬勃发展&#xff0c;水电站在推动地方经济快速增长、缓解能源压力方面发挥了不可替代的作用。然而带来的生态环境问题日益凸显&#xff0c;因水电站下泄流量不足造成部分河段减水、脱水甚至干涸&#xff0c;影响了河流的正常生态功能和居民的生产、生活。因…

【硬件操作入门】2--GPIO与门电路、二极管三极管、LED电路与操作

【硬件操作入门】2–GPIO与门电路&#xff08;二极管&三极管&#xff09;、LED电路与操作 文章目录 【硬件操作入门】2--GPIO与门电路&#xff08;二极管&三极管&#xff09;、LED电路与操作一、GPIO与门电路1.1、GPIO的应用1.2、GPIO引脚操作1.2.1 设置引脚为GPIO功能…

day39(8/29)——harbor私有仓库管理

一、harbor私有仓库管理 是python的包管理工具&#xff0c;和yum对redhat的关系是一样的 yum -y install epel-release yum -y install python2-pip pip install --upgrade pip pip list pip 8x pip install --upgrade pip pip install --upgrade pip20.3 -i https://mirror…

RFID光触发标签在文件柜管理中的创新应用

在当今信息化时代&#xff0c;文件管理对于企业和机构的重要性不言而喻。传统的文件柜管理方式存在诸多问题&#xff0c;如查找文件困难、管理效率低下、安全性难以保障等。而 RFID 光触发标签技术的出现&#xff0c;为文件柜管理带来了全新的解决方案。 一、传统文件柜管理的…

Spring扩展点系列-@PostConstruct

简介 spring的Bean在创建的时候会进行初始化&#xff0c;而初始化过程会解析出PostConstruct注解的方法&#xff0c;并反射调用该方法。 PostConstruct 的使用和特点 只有一个非静态方法能使用此注解&#xff1b;被注解的方法不得有任何参数&#xff1b;被注解的方法返回值必…

实际开发中git在IDEA中的使用

相信搜索这个的同学代码都已经拉取到本地了&#xff0c;并且已经在idea中打开了。 1.一般我们从远程colone下来的代码默认是在主分支下的&#xff0c;也就是说我们从远程的主分支拉取的代码并且在本地创建了一个主分支。 2.一般主分支是不允许修改的&#xff0c;所以我们可以基…

SpringBoot2:配置绑定与自动配置功能源码解读

一、配置绑定 1、作用说明 我们在开发springboot项目时&#xff0c;会有个配置文件&#xff0c;application.properties文件。 我们知道&#xff0c;像什么访问端口、上传功能的相关配置&#xff0c;都会在这里进行配置。 而这些&#xff0c;都是springboot自带的或者第三方j…

Linux | 匿名管道和命名管道:进程间通信数据流的桥梁

目录 1、进程间通信目的 2、管道——匿名管道和命名管道 匿名管道 匿名管道的示例代码&#xff1a;将数据写入管道、子进程从管道读取数据并将其输出到bash中 父子进程通过匿名管道建立通信 重点&#xff1a;管道的五个特点 命名管道&#xff08;也称为FIFO&#xff09;…

每日一题,零基础入门FPGA——工程师在线精讲,直播预告

题目传送门&#xff1a;F学社 zzfpga.com/StudentPlatform/Sheet/QuestionBankhttp://zzfpga.com/StudentPlatform/Sheet/QuestionBank 【第Ⅰ期题目 * 5】 请使用D触发器和必要的逻辑门实现此同步时序电路&#xff0c;用Verilog语言描述。 【第Ⅰ期题目 * 4】 请设计一个0…

观测云核心技术揭秘:基于时间的半结构化数据模型

前言 众所周知&#xff0c;真正意义上的统一监控观测平台本质上是一个超大的数据湖&#xff0c;其存储了大量的来自监控指标&#xff0c;各种各样的日志&#xff0c;各种各样的链路追踪以及包括用户访问行为等海量的可观测性数据。 这些海量数据有什么特点呢&#xff1f; 首先…

【网络安全】逻辑漏洞:绕过应用程序重要功能

未经许可,不得转载。 文章目录 正文漏洞影响正文 目标:xxx.com 一个流行的汽车平台,允许用户为经销商留下评论。该平台有一个功能,用户可以点赞评论,并且它限制每个用户对每个评论只能点赞一次。 然而,我找到了绕过的方法(并不是并发)。 在点击“点赞”按钮时拦截请…

新手指南 | 研发人员奖金激励方案步骤实操

研发团队是一个非常独特的存在。在研发人员的薪酬、激励方案设计上也是很多HR的痛点。 毕竟工作变化大&#xff0c;职责变化快、个体能力差异大、投入了不一定会有产出、多线程并行&#xff0c;贡献难判定、知识密度高&#xff0c;价值难衡量等等... 基于以上难点&#xff0c…

【系统架构设计】嵌入式系统设计(1)

【系统架构设计】嵌入式系统设计&#xff08;1&#xff09; 嵌入式系统概论嵌入式系统的组成硬件嵌入式处理器总线存储器I/O 设备与接口 软件 嵌入式开发平台与调试环境交叉平台开发环境交叉编译环境调试 嵌入式系统概论 嵌入性、专用性、计算机系统是嵌入式系统的三个基本的核…

0基础轻松玩转.NET Web API 8.0【CICD】项目实战

1.背景 最近在学习CI/CD&#xff0c;为了加快熟悉CI/CD&#xff0c;我实操了下基于.Net 8.0的CI/CD项目实战。Ci/CD就是自动化作业&#xff0c;实现项目自动编译、发布、执行等&#xff0c;也有用于拉取推送数据的场景。本文主要介绍了在win 11下搭建CI/CD&#xff0c;实现自动…

UEFI——PCD的简单使用

一、PCD的定义及概念 在UEFI固件接口中&#xff0c;PCD&#xff08;Platform Configuration Database&#xff09;是一个用于存储和访问平台特定配置信息的机制。PCD允许UEFI驱动程序和应用程序在运行时获取和设置平台相关的参数&#xff0c;而无需硬编码这些值。PCD变量可以被…

加速电商物流效率:推荐几款实用的快递批量查询工具

做电商必不可少的快递批量查询平台分享&#xff1a;固乔快递查询助手使用全攻略 在电商行业日益竞争的今天&#xff0c;高效管理物流信息成为了商家们不可或缺的一环。面对每天成百上千的订单和快递单号&#xff0c;如何快速、准确地查询并跟踪物流状态&#xff0c;成为了电商…

stun和trun

在 WebRTC 中&#xff0c;STUN&#xff08;Session Traversal Utilities for NAT&#xff09;和 TURN&#xff08;Traversal Using Relays around NAT&#xff09;是用于NAT穿透的两种不同的技术&#xff0c;它们解决的问题不同&#xff0c;因此在某些情况下需要同时使用。 ST…