当前位置: 首页 > news >正文

快速排序(分治思想)

什么是快速排序

        快速排序(Quick Sort)是一种广泛使用的高效排序算法,由计算机科学家托尼·霍尔在1960年提出。它采用分治法(Divide and Conquer)策略,将一个大数组分为两个小数组,然后递归地对这两个小数组进行排序。快速排序在平均情况下具有良好的性能,时间复为 O(nlog⁡n)O(nlogn),并且在实际应用中通常比其他 O(nlog⁡n)O(nlogn) 的排序算法(如归并排序和堆排序)更快。

核心思想

快速排序的核心思想可以概括为以下几个步骤:

  1. 选择基准(Pivot):从数组中选择一个元素作为基准。基准的选择可以影响排序的效率,常见的选择方法包括选择第一个元素、最后一个元素或随机选择。
  2. 分区(Partition):通过一趟扫描,将数组分为两个部分:
    • 小于等于基准的元素
    • 大于基准的元素
    这个过程称为分区。在分区完成后,基准元素将处于其最终位置。
  3. 递归排序:对基准元素左侧和右侧的子数组进行递归调用快速排序。
  4. 合并结果:由于基准元素已经在正确的位置,最终的排序结果将由所有递归调用的结果自动合并。   

两个指针的定义和移动

在快速排序的实现中,我们使用两个指针 i 和 j 来进行分区操作。

  • i 指针从左到右扫描数组,找到第一个大于基准的元素。
  • j 指针从右到左扫描数组,找到第一个小于等于基准的元素。
  • 当 i 小于 j 时,交换 i 和 j 指向的元素。

这个过程一直持续到 i 大于等于 j,此时分区操作完成。

根据基准值交换

        在分区过程中,当 i 小于 j 时,我们需要交换 i 和 j 指向的元素。这样可以确保左侧的元素都小于等于基准,右侧的元素都大于基准。

        让我们来看两道题目带你快速上手

示例一

题目描述

代码

import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);int n = scanner.nextInt();int arr[] = new int[n];for (int i = 0; i < n; i++) {arr[i] = scanner.nextInt();}quickSort(arr, 0, n-1);for (int i = 0; i < n; i++) {System.out.print(arr[i] + " ");}}public static void quickSort(int[] arr,int l,int r) {if (l >= r) return;int x = arr[l+r >> 1];int i = l - 1, j = r + 1;while (i < j) {do ++i;while (arr[i] < x) ;do --j;while (arr[j] > x);if (i < j) {int temp = arr[i];arr[i] = arr[j];arr[j] = temp;}}quickSort(arr, l, j);quickSort(arr, j + 1, r);}
}

解释

  • Scanner scanner = new Scanner(System.in);:创建一个Scanner对象,用于读取输入。
  • int n = scanner.nextInt();:读取数组的长度。
  • int arr[] = new int[n];:创建一个长度为n的整数数组。
  • for (int i = 0; i < n; i++) { arr[i] = scanner.nextInt(); }:循环读取数组的元素。
  • quickSort(arr, 0, arr.length-1);:调用quickSort方法对数组进行排序。
  • for (int i = 0; i < n; i++) { System.out.print(arr[i] + " "); }:输出排序后的数组。
  • if (l >= r) return;:如果左边界l大于或等于右边界r,则直接返回,因为这意味着子数组只有一个元素或为空,不需要排序。
  • int x = arr[l];:选择数组的第一个元素作为基准元素。
  • int i = l - 1, j = r + 1;:初始化两个指针ij,分别指向数组的左边界的前一个位置和右边界的后一个位置。
  • while (i < j) { ... }:进入主循环,直到ij指针相遇。
  • if (i < j) { ... }:如果ij指针没有相遇,交换arr[i]arr[j]的值。
  • do --j; while (arr[j] > x);j指针从右向左移动,直到找到一个小于或等于基准元素的元素。
  • do ++i; while (arr[i] < x);i指针从左向右移动,直到找到一个大于或等于基准元素的元素。
  • quickSort(arr, l, j);:递归地对左子数组进行排序(从lj)。
  • quickSort(arr, j + 1, r);:递归地对右子数组进行排序(从j + 1r)。

示例二

题目描述

代码

import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner sc = new Scanner(System.in);int n,k;n = sc.nextInt();k = sc.nextInt();int[] arr = new int[n];for (int i = 0; i < n; i++) {arr[i] = sc.nextInt();}quickSort(arr, 0, n - 1);System.out.println(arr[k - 1]);}public static void quickSort(int[] arr,int l,int r) {if (l >= r) return;int x = arr[l];int i = l - 1, j = r + 1;while (i < j) {do ++i; while (arr[i] < x) ;do --j; while (arr[j] > x);if (i < j) {int temp = arr[i];arr[i] = arr[j];arr[j] = temp;}}quickSort(arr, l, j);quickSort(arr, j + 1, r);}
}

解释

  1. 导入Scanner类

    • 用于读取输入数据。
  2. 定义类和main方法

    • Scanner sc = new Scanner(System.in);:创建Scanner对象从标准输入读取数据。
    • int n, k;:声明两个整数nk
    • n = sc.nextInt(); k = sc.nextInt();:读取数组长度n和目标索引k
    • int[] arr = new int[n];:创建长度为n的整数数组。
    • for (int i = 0; i < n; i++) { arr[i] = sc.nextInt(); }:从输入中读取n个整数,存入数组arr
    • quickSort(arr, 0, n - 1);:调用quickSort方法对数组进行排序。
    • System.out.println(arr[k - 1]);:输出排序后数组的第k个元素(下标从0开始,所以是k-1)。
  3. quickSort方法

    • 使用快速排序算法对数组arr的从lr部分进行排序。
    • if (l >= r) return;:如果左边界l大于或等于右边界r,则返回(子数组为空或只有一个元素)。
    • int x = arr[l];:选择子数组的第一个元素作为基准。
    • int i = l - 1, j = r + 1;:初始化两个指针,ij
    • 通过while循环将数组分割为两个部分,所有小于基准值的元素放在左边,所有大于基准值的元素放在右边,并递归地对两边进行快速排序。

总结

        快速排序是一种高效的排序算法,它采用分治法的思想,通过递归的方式将数组分为两个子数组,然后对这两个子数组进行排序。通过选择基准、分区和递归调用,快速排序能够在平均情况下以 O(nlog⁡n)O(nlogn) 的时间复杂度完成排序。尽管在最坏情况下可能退化为 O(n2)O(n2),但通过合理的基准选择和随机化策略,可以有效避免这一问题。快速排序的空间效率和实际性能使其成为排序任务中的热门选择。

相关文章:

快速排序(分治思想)

什么是快速排序 快速排序&#xff08;Quick Sort&#xff09;是一种广泛使用的高效排序算法&#xff0c;由计算机科学家托尼霍尔在1960年提出。它采用分治法&#xff08;Divide and Conquer&#xff09;策略&#xff0c;将一个大数组分为两个小数组&#xff0c;然后递归地对这两…...

JAVA相关知识

JAVA基础知识 说一下对象创建的过程&#xff1f; 类加载检查&#xff1a;当Java虚拟机&#xff08;JVM&#xff09;遇到一个类的new指令时&#xff0c;它首先检查这个类是否已经被加载、链接和初始化。如果没有&#xff0c;JVM会通过类加载器&#xff08;ClassLoader&#xff…...

详解TCP的三次握手

TCP&#xff08;三次握手&#xff09;是指在建立一个可靠的传输控制协议 (TCP) 连接时&#xff0c;客户端和服务器之间的三步交互过程。这个过程的主要目的是确保连接是可靠的、双方的发送与接收能力是正常的&#xff0c;并且可以开始数据传输。下面是对每个步骤的详细解释&…...

Java面试篇基础部分-Java创建线程详解

导语   多线程的方式能够在操作系统的多核配置上更好的利用服务器的多个CPU的资源,这样的操作可以使得程序运行起来更加高效。Java中多线程机制提供了在一个进程内并发去执行多个线程,并且每个线程都并行的去执行属于线程处理的自己的任务,这样可以提高程序的执行效率,让…...

Ubuntu 20.04/22.04无法连接网络(网络图标丢失、找不到网卡)的解决方案

问题复述&#xff1a; Ubuntu 20.04无法连接到网络&#xff0c;网络连接图标丢失&#xff0c;网络设置中无网络设置选项。 解决方案 对于Ubuntu 20.04而言&#xff1a;逐条执行 sudo service network-manager stopsudo rm /var/lib/NetworkManager/NetworkManager.statesudo…...

《MDTv2- Masked Diffusion Transformer is a Strong Image Synthesizer》

论文摘要 论文提出了一种名为**Masked Diffusion Transformer (MDT)**的新模型&#xff0c;旨在增强扩散概率模型&#xff08;DPMs&#xff09;在图像合成中的上下文推理能力。通过引入掩码潜在建模方案&#xff0c;MDT能够显著提升DPMs在图像中对象部分之间关系的学习能力&am…...

算法 - 二分查找

算法 - 二分查找 今天继续八股文学习&#xff0c;看一下比较常规的几个算法 二分查找是一个基于分治策略的搜索方法&#xff0c;简单的理解就是每次都缩小一轮搜索范围&#xff0c;从中间search一次&#xff0c;直到搜索到结果或者为空为止。 基本思路&#xff08;设一个有序的…...

Python知识点:如何使用Python进行图像批处理

在Python中进行图像批处理可以使用多种库&#xff0c;如 Pillow、OpenCV 和 imageio。这些库可以用来执行各种图像处理任务&#xff0c;如调整大小、裁剪、旋转、滤镜应用等。以下是使用这些库进行图像批处理的示例。 使用 Pillow 进行图像批处理 Pillow 是一个功能强大的图像…...

数据结构实验1

实验题1&#xff1a;求1到n的连续整数和 题目描述 编写一个程序,对于给定的正整数n,求12…十n,采用逐个累加与(n1)/2(高斯法)两种解法。对于相同的n,给出这两种解法的求和结果和求解时间,并用相关数据进行测试。 运行代码 //实验题1&#xff1a;求1到n的连续整数和 #includ…...

使用Postman+JMeter进行简单的接口测试

以前每次学习接口测试都是百度&#xff0c;查看相关人员的实战经验&#xff0c;没有结合自己公司项目接口真正具体情况。 这里简单分享一下公司项目Web平台的一个查询接口&#xff0c;我会使用2种工具Postman和JMeter如何对同一个接口做调试。 准备工作 首先&#xff0c;登录公…...

基于 SpringBoot 的车辆充电桩管理系统

专业团队&#xff0c;咨询就送开题报告 摘 要 随着信息化时代的到来&#xff0c;管理系统都趋向于智能化、系统化&#xff0c;车辆充电桩管理系统也不例外&#xff0c;但目前国内仍都使用人工管理&#xff0c;市场规模越来越大&#xff0c;同时信息量也越来越庞大&#xff0c;…...

centos7.9安装clamav教程

本章教程主要记录在centos7.9安装clamav过程。 ClamAV(Clam AntiVirus)是一个开源的防病毒软件工具,主要用于检测和消除恶意软件。它最初由 Tomasz Kojm 于 2001 年开发,并由 Cisco Systems 维护和支持。ClamAV 广泛应用于邮件网关、文件服务器和其他需要防病毒保护的环境中…...

产品经理如何转型为AI产品经理,如何理解AI产品工程化

技术领域,特别是人工智能和机器学习,其优秀模型的成功应用是一个复杂过程,它不仅要求技术本身的卓越,还须与现有解决方案竞争,这涉及到技术成熟度、成本有效性、市场接受度等多维度因素。 在这一过程中,产品经理扮演着核心角色,负责协调各方利益,确保技术能够转化为满…...

TiDB从0到1学习笔记(精华篇)

历时四个月&#xff0c;恭喜赵老师的《TiDB从0到1》 系列文章顺利完结&#xff0c;小编再次梳理一遍文稿&#xff0c;并附注解分享给大家。 整体架构 从 TiDB 1.0 到 8.0&#xff0c;TiDB 的体系结构一直在不断演进。接下来让我们一起看看整体架构的变化。 TiDB v1 TiDB v1&…...

NLP-新词挖掘

一、背景 网络领域的新词发现&#xff08;挖掘&#xff09;是一个非常重要的nlp课题。在处理文本对象时&#xff0c;非常关键的问题在于“切词”这个环节&#xff0c;几乎所有的后续结果都依赖第一步的切词。因此切词的准确性在很大程度上影响着后续的处理&#xff0c;切词结果…...

电脑录屏不求人,9月必备免费录屏软件推荐!苹果电脑可用!

在当今这个信息爆炸的时代&#xff0c;电脑录屏软件已经成为了我们日常工作和生活中不可或缺的工具。无论是制作教学视频、录制在线课程、游戏直播&#xff0c;还是创建产品演示&#xff0c;一个好的录屏软件都能帮助我们更高效地完成任务。市场上的录屏软件琳琅满目&#xff0…...

SpringMVC基于注解使用:国际化

01-国际化介绍 首先在bootstrap下载个页面 下载后把登录页面的代码粘上去 然后再登录页面代码上有些超链接需要再spring-mvc.xml里面配置下&#xff0c;登录页面才能正常显示 配置静态资源 国际化-根据浏览器语言国际化 现在是中文的情况&#xff0c;要改为英文 1.配置下属…...

工地安全帽检测系统源码分享

工地安全帽检测检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Computer V…...

如何为 DigitalOcean 静态路由操作员设置故障转移

静态路由操作器的主要目的是提供更大的灵活性&#xff0c;并在 Kubernetes 环境中控制网络流量。它使你能够根据应用程序的需求自定义路由配置&#xff0c;从而优化网络性能。该操作器作为 DaemonSet 部署&#xff0c;因此将在你的 DigitalOcean Managed Kubernetes 集群的每个…...

Ansible简单部署与使用

目录 环境安装Ansibleapt installmarkupsafe error 配置Ansible创建个人目录ansible.cfghosts 测试Ansibleping批量执行自定义命令 环境 Ubuntu 20.04 安装Ansible apt install sudo apt install ansiblemarkupsafe error 安装成功后&#xff0c;尝试运行ansible&#xff…...

Android Wi-Fi 连接失败日志分析

1. Android wifi 关键日志总结 (1) Wi-Fi 断开 (CTRL-EVENT-DISCONNECTED reason3) 日志相关部分&#xff1a; 06-05 10:48:40.987 943 943 I wpa_supplicant: wlan0: CTRL-EVENT-DISCONNECTED bssid44:9b:c1:57:a8:90 reason3 locally_generated1解析&#xff1a; CTR…...

pikachu靶场通关笔记22-1 SQL注入05-1-insert注入(报错法)

目录 一、SQL注入 二、insert注入 三、报错型注入 四、updatexml函数 五、源码审计 六、insert渗透实战 1、渗透准备 2、获取数据库名database 3、获取表名table 4、获取列名column 5、获取字段 本系列为通过《pikachu靶场通关笔记》的SQL注入关卡(共10关&#xff0…...

纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join

纯 Java 项目&#xff08;非 SpringBoot&#xff09;集成 Mybatis-Plus 和 Mybatis-Plus-Join 1、依赖1.1、依赖版本1.2、pom.xml 2、代码2.1、SqlSession 构造器2.2、MybatisPlus代码生成器2.3、获取 config.yml 配置2.3.1、config.yml2.3.2、项目配置类 2.4、ftl 模板2.4.1、…...

STM32HAL库USART源代码解析及应用

STM32HAL库USART源代码解析 前言STM32CubeIDE配置串口USART和UART的选择使用模式参数设置GPIO配置DMA配置中断配置硬件流控制使能生成代码解析和使用方法串口初始化__UART_HandleTypeDef结构体浅析HAL库代码实际使用方法使用轮询方式发送使用轮询方式接收使用中断方式发送使用中…...

链式法则中 复合函数的推导路径 多变量“信息传递路径”

非常好&#xff0c;我们将之前关于偏导数链式法则中不能“约掉”偏导符号的问题&#xff0c;统一使用 二重复合函数&#xff1a; z f ( u ( x , y ) , v ( x , y ) ) \boxed{z f(u(x,y),\ v(x,y))} zf(u(x,y), v(x,y))​ 来全面说明。我们会展示其全微分形式&#xff08;偏导…...

PCA笔记

✅ 问题本质&#xff1a;为什么让矩阵 TT 的行列式为 1&#xff1f; 这个问题通常出现在我们对数据做**线性变换&#xff08;旋转/缩放&#xff09;**的时候&#xff0c;比如在 PCA 中把数据从原始坐标系变换到主成分方向时。 &#x1f4cc; 回顾一下背景 在 PCA 中&#xff…...

MAZANOKE结合内网穿透技术实现跨地域图像优化服务的远程访问过程

文章目录 前言1. 关于MAZANOKE2. Docker部署3. 简单使用MAZANOKE4. 安装cpolar内网穿透5. 配置公网地址6. 配置固定公网地址总结 前言 在数字世界高速发展的今天&#xff0c;您是否察觉到那些静默增长的视觉数据正在悄然蚕食存储空间&#xff1f;随着影像记录成为日常习惯&…...

centos挂载目录满但实际未满引发系统宕机

测试服务器应用系统突然挂了&#xff0c;经过排查发现是因为磁盘“满了”导致的&#xff0c;使用df -h查看磁盘使用情况/home目录使用率已经到了100%,但使用du -sh /home查看发现实际磁盘使用还不到1G&#xff0c;推测有进程正在写入或占用已删除的大文件&#xff08;Linux 系统…...

html - <mark>标签

<mark> 标签在HTML中用于高亮显示文本&#xff0c;通常用于突出显示某些重要的部分。它的默认样式通常是背景色为黄色&#xff0c;但你可以通过CSS自定义其外观。 1. 基本用法 <mark> 标签用于标记文本的高亮显示。它常用于搜索结果中&#xff0c;突出显示匹配的…...

LabVIEW工业级多任务实时测控系统

采用LabVIEW构建了一套适用于工业自动化领域的多任务实时测控系统。系统采用分布式架构&#xff0c;集成高精度数据采集、实时控制、网络通信及远程监控等功能&#xff0c;通过硬件与软件的深度协同&#xff0c;实现对工业现场多类型信号的精准测控&#xff0c;展现 LabVIEW 在…...