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

题集-三路划分和三数取中(快排优化)

快排排序是非常快的,但是有一种情况快排是无法进行的。

912. 排序数组 - 力扣(LeetCode)

这道题看上去没什么问题,但是如果我们用快排去提交的话,发现快排其实是被针对了的。

有一个样例是这样的。如果我们按照快排的思想,right指针将一路狂奔到left指针这里回合,然后每次分割区间都是只分割出去一个数,这样就会造成时间超限。

所以我们将快排进行优化,实现三路划分

原来的快排思想是将小于等于key的放在左边,将大于等于key的放在右边,这样形成了两个区间。

三路划分的思想其实就是,将小于key的放在左边,将大于key的放在右边,将等于key的放在中间。

然后分割区间的时候,左边小于key的一个,右边大于key的一个,中间的就不用再动了

具体操作的方法:

还是left在左侧,right在右侧,current遍历。

当current遇到比key小的,就将current下的值和left交换,然后将left++,current++。(因为left为和key相等的值,交换过后left++,相当于是left左边是比key小的值,left永远指向和key相等的值)

当current遇到和key相等的值时,就将current++,继续遍历。

当current遇到比key大的值,就将current下的值和right交换,然后将right--(不先管right原位置的值的大小,先交换,此时right--后,right右侧的值则永远都是比key大的值,current不动,因为不确定交换后的值的大小。进行新一轮的比较之后,再决定去留)

代码:


/*** Note: The returned array must be malloced, assume caller calls free().*/int GetMidIndex(int* a, int left, int right)
{int mid = (left + right) / 2;if (a[left] < a[mid]){if (a[mid] < a[right])return mid;else if (a[right] < a[left]){return left;}else return right;}else{if (a[mid] > a[right])return mid;else if (a[left] < a[right])return left;else return right;}}void Swap(int* p1, int* p2)
{int tmp = *p1;*p1 = *p2;*p2 = tmp;
}void QuickSort(int* a, int begin, int end)
{if (begin >= end){  return;}int left = begin;int current = left+1;int right = end;int midi = GetMidIndex(a, left, right);Swap(&a[left], &a[midi]);int key = a[left];while (current <= right){if(a[current] > key){Swap(&a[current], &a[right]);right--;}else if(a[current] < key){Swap(&a[current], &a[left]);left++;current++; }else current++;}QuickSort(a, begin,left-1);QuickSort(a, right+1, end);
}
int* sortArray(int* nums, int numsSize, int* returnSize){QuickSort(nums,0,numsSize-1);*returnSize = numsSize;return nums;
}

提交还有样例没过

做出三路划分后,这个样例针对的是快排的三数取中(GetMidIndex)方法。

但是如果去掉三数取中方法,当遇到接近有序的序列后就会超时。所以我们不能用普通的三数取中方法。

 int GetMidIndex(int* a, int left, int right)
{int mid = left+(rand()%(right-left));      //中间的数不再固定。if (a[left] < a[mid]){if (a[mid] < a[right])return mid;else if (a[right] < a[left]){return left;}else return right;}else{if (a[mid] > a[right])return mid;else if (a[left] < a[right])return left;else return right;}}

这样,这道题就可以用快排的方法提交了。

http://www.lryc.cn/news/149814.html

相关文章:

  • 设计模式-迭代器
  • Hive学习(12)Hive常用日期函数
  • PowerQuery动态加载M公式
  • 2分钟搭建FastGPT训练企业知识库AI助理(Docker部署)
  • TDengine函数大全-字符串函数
  • part-02 C++知识总结(类型转换)
  • stable diffusion实践操作-图生图
  • Jtti:Ubuntu18.04如何修改远程ssh端口号
  • 微软表示Visual Studio的IDE即日起开启“退休”倒计时
  • 好马配好鞍:Linux Kernel 4.12 正式发布
  • element——switch接口成功后赋值打开开关
  • WPF Border设置渐变色
  • SAP_ABAP_OLE_EXCEL批导案例
  • MySQL以及版本介绍
  • stm32 iap sd卡升级
  • D358周赛复盘:哈希表模拟⭐⭐+链表乘法翻倍运算(先反转)⭐⭐⭐
  • java八股文面试[数据库]——索引的基本原理、设计原则
  • 2023年京东方便食品行业数据分析(京东数据报告)
  • 无涯教程-Android - Style Demo Example函数
  • 【算法训练-字符串 二】最长回文子串
  • 结合OB Cloud区别于MySQL的4大特性,规划降本方案
  • 题目有点太简单了,不知道怎么选了
  • Bug:mac上运行go run main.go 报错,fork/exec /var/fold/T/go-build269/b001/ex
  • CSRF与XSS结合利用
  • 【爬虫】实验项目一:文本反爬网站的分析和爬取
  • DEAP库文档教程二-----创建类型
  • Axure RP美容美妆医美行业上门服务交互原型图模板源文件
  • 【SpringBoot】用SpringBoot代码详细解释<List>的用法
  • HRS--人力资源系统(Springboot+vue)--打基础升级--(六)分页查询 + 重置按钮
  • JavaScript设计模式(二)——简单工厂模式、抽象工厂模式、建造者模式