912.排序数组

目录

  • 题目
  • 解法
      • 步骤 1:调用 `randomized_partition`
      • 步骤 2:递归调用 `randomized_quicksort`
      • 最终结果:
      • 变量变化总结:
  • 为什么要把主元放到最后一个?
  • partition返回得到的是什么下标?

题目

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

你必须在 不使用任何内置函数 的情况下解决问题,时间复杂度为 O(nlog(n)),并且空间复杂度尽可能小。

解法

class Solution {int partition(vector<int>& nums, int l, int r) {int pivot = nums[r];int i = l - 1;for (int j = l; j <= r - 1; ++j) {if (nums[j] <= pivot) {i = i + 1;swap(nums[i], nums[j]);}}swap(nums[i + 1], nums[r]);return i + 1;}int randomized_partition(vector<int>& nums, int l, int r) {int i = rand() % (r - l + 1) + l; // 随机选一个作为我们的主元swap(nums[r], nums[i]);return partition(nums, l, r);}void randomized_quicksort(vector<int>& nums, int l, int r) {if (l < r) {int pos = randomized_partition(nums, l, r);randomized_quicksort(nums, l, pos - 1);randomized_quicksort(nums, pos + 1, r);}}
public:vector<int> sortArray(vector<int>& nums) {srand((unsigned)time(NULL));randomized_quicksort(nums, 0, (int)nums.size() - 1);return nums;}
};

我们通过一个例子来展示快速排序代码中变量的动态变化。假设我们要排序的数组为 nums = [3, 6, 8, 10, 1, 2, 1]。这个数组会通过randomized_quicksort方法进行排序。

初始状态:

  • nums = [3, 6, 8, 10, 1, 2, 1]
  • l = 0(左边界)
  • r = 6(右边界)

步骤 1:调用 randomized_partition

randomized_partition 随机选取一个元素作为主元,这里假设随机选择的是 nums[2] = 8,然后将其和最后一个元素交换,nums[r] = 1。交换后的数组为:

  • nums = [3, 6, 1, 10, 1, 2, 8](选定的主元 8 被放置到了最后)

接着,调用 partition 方法,对数组进行划分:

  • pivot = 8(主元)

  • i = -1(指向小于等于主元的区域的边界)

  • j = 0 开始遍历数组:

    • nums[0] = 33 <= 8i = 0,交换 nums[0]nums[0](数组不变)。
    • nums[1] = 66 <= 8i = 1,交换 nums[1]nums[1](数组不变)。
    • nums[2] = 11 <= 8i = 2,交换 nums[2]nums[2](数组不变)。
    • nums[3] = 1010 > 8,不做任何操作。
    • nums[4] = 11 <= 8i = 3,交换 nums[3]nums[4],得到 nums = [3, 6, 1, 1, 10, 2, 8]
    • nums[5] = 22 <= 8i = 4,交换 nums[4]nums[5],得到 nums = [3, 6, 1, 1, 2, 10, 8]

遍历结束后,i + 1 = 5,交换 nums[5]nums[6],得到 nums = [3, 6, 1, 1, 2, 8, 10]。返回位置 pos = 5,这意味着主元 8 已经在正确的位置上。

步骤 2:递归调用 randomized_quicksort

对左半部分 nums[0...4] = [3, 6, 1, 1, 2] 进行排序:

  1. 随机选择主元,假设选择 nums[1] = 6,交换 nums[1]nums[4],得到 nums = [3, 2, 1, 1, 6, 8, 10]
  2. 进行 partition 操作,最终将主元 6 放置在正确位置,数组变为 nums = [3, 2, 1, 1, 6, 8, 10],返回位置 pos = 4

对左半部分 nums[0...3] = [3, 2, 1, 1] 继续排序:

  1. 随机选择主元,假设选择 nums[0] = 3,交换 nums[0]nums[3],得到 nums = [1, 2, 1, 3, 6, 8, 10]
  2. 进行 partition 操作,最终主元 3 放置在正确位置,数组变为 nums = [1, 2, 1, 3, 6, 8, 10],返回位置 pos = 3

继续对左右两部分递归,直至完成排序:

  • nums[0...2] = [1, 2, 1] 进行排序,最终得到 nums = [1, 1, 2, 3, 6, 8, 10]
  • 右半部分 nums[6...6] = [10] 不需再排序。

最终结果:

nums = [1, 1, 2, 3, 6, 8, 10]

变量变化总结:

  • 主元 pivot 不断变化,随机选择后与尾部交换。
  • 变量 i 控制已排序区域,j 遍历数组进行比较。

为什么要把主元放到最后一个?

将主元(pivot)放到最后一个元素的主要原因是方便在快速排序的分区过程中进行比较和交换。以下是一些详细的解释:

  1. 简化分区逻辑
    在快速排序中,我们需要重新排列数组,使得所有小于或等于主元的元素都在主元的左侧,而所有大于主元的元素都在右侧。将主元放到最后一个位置后,我们可以通过一个简单的遍历将数组分成两个部分,这样做能够简化比较逻辑。

  2. 便于交换
    在分区过程中,使用最后一个元素作为主元可以使我们在进行元素交换时更加方便。我们可以在遍历过程中保持一个指针 i,该指针表示小于等于主元的元素的边界。每当我们找到一个小于或等于主元的元素时,就将其与 i 指向的元素交换。遍历完成后,只需将主元与 i 后面的元素交换,最终主元就会处于其正确的位置。

  3. 直观的结束条件
    将主元放到数组的最后一个位置,使得我们可以轻松地使用 j 指针遍历数组。在遍历结束后,主元的最终位置可以直接通过指针的计算得出。

  4. 避免主元干扰
    在分区过程中,主元作为一个特殊的元素,其位置在排序过程中不应受到影响。将主元置于最后一位,能够避免在比较和交换时对其产生干扰。

总之,将主元放到最后一个位置是快速排序算法的一个常见策略,它能简化逻辑,提高代码的可读性和效率。

swap(nums[i], nums[j]);

这边是个双指针,i和j都在变化,i是已排序的元素边界,j是遍历整个数组

partition返回得到的是什么下标?

一轮排序完成后得到的主元正确位置。
方便后续进行递归,用pos接收这个位置,递归左右两边(0,pos-1),(pos+1,r)

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

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

相关文章

【数据管理】DAMA-数据资产目录

导读&#xff1a;数据资产目录作为企业级数据管理的核心组成部分&#xff0c;是连接数据生产者与数据消费者的桥梁&#xff0c;更是挖掘数据价值、提升决策效率的关键工具。以下是数据资产目录详细介绍。 目录 1、定义 2、功能和目标 2、目录例子 3、如何编制 一、明确目标…

安卓cpu知识

背景 目前的cpu都是多核的&#xff0c;为了有更好的能效&#xff0c;每个核的频率从低往高不等。市面上&#xff0c;大家根据频率不同&#xff0c;都叫大小核。既然分了大小核&#xff0c;那么多核心&#xff0c;就要有不同的cpu调度策略。所以cpu上的所有核&#xff0c;又会根…

jmeter 从多个固定字符串中随机取一个值的方法

1、先新增用户参数&#xff0c;将固定值设置为不同的变量 2、使用下面的函数&#xff0c;调用这写变量 ${__RandomFromMultipleVars(noticeType1|noticeType2|noticeType3|noticeType4|noticeType5)} 3、每次请求就是随机取的值了

中间件之Seata

一、引言 在微服务架构日益盛行的今天&#xff0c;分布式事务成为了一个必须面对和解决的问题。传统的本地事务已经无法满足分布式环境下的数据一致性需求&#xff0c;因此分布式事务解决方案应运而生。Seata作为一款开源的分布式事务中间件&#xff0c;以其高性能、易用性和灵…

优化多表联表查询的常见方法归纳

目录 一、使用mybatis的嵌套查询 二、添加表冗余字段&#xff0c;减少联表查询需求 三、分表预处理&#xff0c;前端再匹配 一、使用mybatis的嵌套查询 【场景说明】 前端需要展示一张列表&#xff0c;其中的字段来源于多张表&#xff0c;如何进行查询优化&#xff1f; 【…

飞凌嵌入式FET527N-C核心板已适配OpenHarmony4.1

近期&#xff0c;飞凌嵌入式为FET527N-C核心板适配了OpenHarmony4.1系统——进一步提升了核心板的兼容性、稳定性和安全性。 OpenHarmony4.1在应用开发方面展现了全新的开放能力&#xff0c;以更加清晰的逻辑和场景化视角提供给开发者丰富的API接口&#xff0c;应用开发能力得…

让你的 IDEA 使用更流畅 | IDEA内存修改

随着idea使用越来越频繁&#xff0c;笔者最近发现使用过程中有时候会出现卡顿现象&#xff0c;例如&#xff0c;启动软件变慢&#xff0c;打开项目的速度变慢等&#xff1a; 因此如果各位朋友觉得最近也遇到了同样的困惑&#xff0c;不妨跟着笔者一起来设置IDEA的内存大小吧~ …

基于ECS和NAS搭建个人网盘

前言 在数字化时代&#xff0c;数据已成为我们生活中不可或缺的一部分。个人文件、照片、视频等数据的积累&#xff0c;使得我们需要一个安全、可靠且便捷的存储解决方案。传统的物理存储设备&#xff08;如硬盘、U盘&#xff09;虽然方便&#xff0c;但存在易丢失、损坏和数据…

登录前端笔记(二):vuex管理用户数据;跨域;axios封装;环境;请求响应拦截;权限;用户资料Vuex共享

一、Vuex登录流程之用户模块&#xff1a; 简言之&#xff1a;点击登录调用actions且得到token&#xff0c;把得到的token提交给mutations从而修改state里的数据。 原视频 &#xff08;1&#xff09;Vuex用户模块流程 组件页面里点击登录后&#xff0c;调用stores里的actions&…

Springboot实现自动装配

自动装配&#xff08;Auto-wiring&#xff09;是 Spring 框架中的一个重要特性&#xff0c;它是指 Spring 容器在创建和管理 Bean 时&#xff0c;能够自动识别并满足 Bean 之间的依赖关系&#xff0c;无需开发人员显式地在配置文件或代码中指定依赖注入的具体细节。以下是对自动…

09_实现reactive之代理 Set 和 Map

目录 创建代理建立响应式联系避免污染原始数据处理 forEachfor...ofvalues 与 keys 方法 Set 和 Map 都有特定的属性和方法来操作自身&#xff0c;因此需要单独处理。 创建代理 我们来看一段案例代码&#xff0c;体验一下和它们的独特之处&#xff0c;如下&#xff1a; const…

《使用Gin框架构建分布式应用》阅读笔记:p108-p126

《用Gin框架构建分布式应用》学习第8天&#xff0c;p108-p126总结&#xff0c;总计18页。 一、技术总结 1.Redis eviction policy (1)什么是 eviction policy? The eviction policy determines what happens when a database reaches its memory limit. (2)配置示例 在r…

将 Ubuntu 系统中的 **swap** 空间从 2GB 扩展到 16GB

要将 Ubuntu 系统中的 swap 空间从 2GB 扩展到 16GB&#xff0c;可以按照以下步骤操作&#xff1a; 1. 关闭现有 Swap 文件 首先需要禁用当前的 swap 文件&#xff0c;以便重新调整其大小。 sudo swapoff -a2. 删除旧的 Swap 文件 假设当前的 swap 文件位于 /swapfile&…

基于Multisim电子配料秤电路设计(含仿真和报告)

【全套资料.zip】电子配料秤电路设计Multisim仿真设计数字电子技术 文章目录 功能一、Multisim仿真源文件二、原理文档报告资料下载【Multisim仿真报告讲解视频.zip】 功能 电子配料秤仿真功能: 准确测量物体重量&#xff0c;精确度0.1Kg使用两位数码管显示重量信息 使用拨码…

如何将两个同样大小的List组装成一个Map?

如果你有两个同样大小的列表&#xff0c;并且想要将它们组装成一个Map&#xff0c;其中第一个列表的元素作为key&#xff0c;第二个列表的元素作为value&#xff0c;你可以使用Java 8的流&#xff08;Stream&#xff09;API来实现这一操作。 // 假设这是你的两个同样大小的列表…

【C++刷题】力扣-#108-将有序数组转换为二叉搜索树

题目描述 给定一个升序排列的整数数组 nums&#xff0c;将其转换为一棵高度平衡的二叉搜索树&#xff08;BST&#xff09;。高度平衡的二叉搜索树定义为&#xff1a;一个二叉搜索树&#xff0c;其中左右两个子树的高度差不超过 1。 示例 示例 1 输入: nums [-10,-3,0,5,9] 输…

mysql的卸载与安装

一、mysql的卸载 1、用管理员模式的打开cmd&#xff0c;我的服务名是mysql。 net stop mysql sc delete 服务名 2、将下图中有包含‘bin’目录&#xff0c;‘data’目录等等的这个总目录删掉 如图我的目录是&#xff1a;mysql-5.7.28-winx64 3、删除mysql的隐藏文件 C:\Program…

OBOO鸥柏丨《满天星(MTSTAR)》信息发布系统售后服务点位收费标准

户外/室内款系列商用显示屏终端外观贴有OBOO鸥柏品牌铭牌等出厂标识&#xff0c;均为OBOO鸥柏官方出品出厂&#xff0c;均享受永久技术免费服务。认准鸥柏(OBOO)官方出厂等商用液晶显示硬件产品配套。鸥柏(OBOO)满天星(MTSTAR)多媒体信息发布系统是一种集成了多种多媒体元素和技…

在做题中学习(66):两数相加

解法&#xff1a;模拟 思路&#xff1a;定义一个变量t&#xff0c;存储相加后的结果&#xff0c;个位赋给新节点&#xff0c;十位&#xff08;表示有进位&#xff09;留下&#xff0c;累加到下一次加法&#xff08;相当于上进位&#xff09;。while里即便cur1和cur2都为空了&a…

3dsMax 展管道UV

3dsMax 展管道UV 创建管道模型 https://blog.csdn.net/GoodCooking/article/details/140876371有管道模型之后&#xff0c;进行展UV 展开UV之后 旋转UV&#xff0c;大致靠左 挨个拉直拐角 挨个拉直拐角 缩放到UV里面&#xff0c;不要拖拽点。 水平缩放&#xff0c;将U…