【算法】

  选取pivot,然后每趟快排用双指针扫描(l,r)区间,交换左指针大于pivot的元素和右指针小于pivot的元素,将区间分成大于pivot和小于pivot的

【注意】

  时间复杂度取决于pivot的选取是否能把(l,r)区间分成长度相等的两个子区间。

  最优:O(nlogn)  最差:O(n2)

  问题解决:

  1. 版本一:pivot选择区间中间的元素可以解决数组本身就已经排好序的问题,但是无法解决数组中每个元素均相等(第五个点tle)
 #include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5;
int n,p,i,j;
int a[maxn];
void quick_sort(int l,int r)
{
if(l>r) return;
i = l, j = r;
//swap(a[l], a[(l+r)>>]); ------pivot选区间中间的元素
while(i < j) {//i和j相等时停下来
while(a[j]>=a[l] && i < j) j--; //先右再左很关键!若右指针和左指针相遇则此时左指针指向pivot或小于pivot的元素(前一次有交换),若左指针和右指针相遇,则此时
while(a[i]<=a[l] && i < j) i++; //右指针应当已经寻找到的小于pivot的元素;若先左再右,则反过来了。pivot的位置会出错。
if(i<j) swap(a[i],a[j]);
}
swap(a[l],a[j]);
quick_sort(l,i-);
quick_sort(i+,r);
}
int main()
{
cin>>n;
for(int i = ; i <= n; i++)
cin>>a[i];
quick_sort(,n);
for(int i = ; i <= n; i++)
cout << a[i] << " ";
return ;
}

    2、版本二:先判断是否有序,若有序则结束,若无序再按原方法。

    3、版本三:每次分成两个子区间,左区间小于等于pivot,右区间大于等于pivot,但不一定确定好pivot的位置,但最终区间长度为2或3的时候必定能确定好

        ------------------------感觉这种要好写一点,理解了之后,其实都是细节------------------------

 #include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5;
int n,p,i,j;
int a[maxn];
void quick_sort(int l,int r)
{
int pivot = a[(l+r)>>];
i = l, j = r;
while(i <= j) { //直到i>j为止,就算数组元素均相等也会向前推进
while(a[i] < pivot) i++;
while(a[j] > pivot) j--;
if(i <= j) {
swap(a[i],a[j]);
i++, j--;
}
}
if(i < r) quick_sort(i,r);
if(j > l) quick_sort(l,j);
}
int main()
{
cin>>n;
for(int i = ; i <= n; i++)
cin>>a[i];
quick_sort(,n);
for(int i = ; i <= n; i++)
cout << a[i] << " ";
return ;
}

    4、找第k大的数:分治法类似快排的方法,平均复杂度O(n)【1+2+4+。。。+n/2+n】按版本三的话不太好写,就按版本一来吧:

 #include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5;
int n,k,i,j;
int a[maxn];
int quick_find(int l,int r,int k)
{
int pivot = a[(l+r)>>], rec = ;
i = l, j = r;
swap(a[(l+r)>>], a[l]);
while(i < j) {
while(a[j] >= pivot && i < j) j--, rec++;
while(a[i] <= pivot && i < j) i++;
if(i < j) swap(a[i],a[j]);
}
swap(a[i],a[l]);
if(k == rec + ) return a[i];
else if(k <= rec) return quick_find(i+,r,k);
else return quick_find(l, i-, k-rec-); }
int main()
{
cin>>n>>k;
for(int i = ; i <= n; i++)
cin>>a[i];
cout<<quick_find(,n,k)<<endl;
return ;
}

 

luogu_P1177 【模板】快速排序 (快排和找第k大的数)的更多相关文章

  1. 快排法求第k大

    快排法求第k大,复杂度为O(n) import com.sun.media.sound.SoftTuning; import java.util.Arrays; import java.util.Ra ...

  2. 找第k大的数

    (找第k大的数) 给定一个长度为1,000,000的无序正整数序列,以及另一个数n(1<=n<=1000000),接下来以类似快速排序的方法找到序列中第n大的数(关于第n大的数:例如序列{ ...

  3. P1049 找第K大的数

    题目描述 给定一个无序正整数序列, 以及另一个数n (1<=n<=1000000), 然后以类似快速排序的方法找到序列中第n大的数(关于第n大的数:例如序列{1,2,3,4,5,6}中第3 ...

  4. 快速排序算法的实现 && 随机生成区间里的数 && O(n)找第k小 && O(nlogk)找前k大

    思路:固定一个数,把这个数放到合法的位置,然后左边的数都是比它小,右边的数都是比它大 固定权值选的是第一个数,或者一个随机数 因为固定的是左端点,所以一开始需要在右端点开始,找一个小于权值的数,从左端 ...

  5. 找出N个无序数中第K大的数

    使用类似快速排序,执行一次快速排序后,每次只选择一部分继续执行快速排序,直到找到第K个大元素为止,此时这个元素在数组位置后面的元素即所求 时间复杂度: 1.若随机选取枢纽,线性期望时间O(N) 2.若 ...

  6. 找出整数中第k大的数

    一  问题描述: 找出 m 个整数中第 k(0<k<m+1)大的整数. 二  举例: 假设有 12 个整数:data[1, 4, -1, -4, 9, 8, 0, 3, -8, 11, 2 ...

  7. 基于快速排序思想partition查找第K大的数或者第K小的数。

    快速排序 下面是之前实现过的快速排序的代码. function quickSort(a,left,right){ if(left==right)return; let key=partition(a, ...

  8. 寻找第K大的数(快速排序的应用)

    有一个整数数组,请你根据快速排序的思路,找出数组中第K大的数.给定一个整数数组a,同时给定它的大小n和要找的K(K在1到n之间),请返回第K大的数,保证答案存在.测试样例:[1,3,5,2,2],5, ...

  9. 算法题之找出数组里第K大的数

    问题:找出一个数组里面前K个最大数. 解法一(直接解法): 对数组用快速排序,然后直接挑出第k大的数.这种方法的时间复杂度是O(Nlog(N)).N为原数组长度. 这个解法含有很多冗余,因为把整个数组 ...

随机推荐

  1. cookie、session和中间件

    目录 cookie和session cookie与session原理 cookie Google浏览器查看cookie Django操作cookie 获取cookie 设置cookie 删除cooki ...

  2. css----动画(图片无限放大缩小)

    先给大家推荐animate.css库,里面有一些效果很不错的过度样式,不想自己写的也可以直接安装这个库来使用,如果不想安装这个库也可以去https://daneden.github.io/animat ...

  3. Xcode 代码注释

    /** * 生成二维码 * * @param data 二维码数据 * @param size 二维码大小 * @param color 二维码颜色 * @param backgroundColor ...

  4. 开发工具Intellij IDEA:面板介绍

    一.面板说明 IDEA面板的全貌如下图 2|0 二.菜单栏 下面会简单介绍下一些常用的部分菜单使用,如有疑问或补充欢迎留言. (1).File文件 1. New:新建一个工程 可以新建project, ...

  5. 死锁(deadlocks)

    1.定义 所谓死锁<DeadLock>: 是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象.若无外力作用,它们都将无法推进下去,此时称系统处于死锁状态或系统产生了 ...

  6. ndn挖坑记(二)

    目录 如何使用ndnSIM运行自己的仿真实验 基本要点 开始动手 BUG记录 如何使用ndnSIM运行自己的仿真实验 基本要点 仿真场景可以在NS-3目录下的scratch/ or src/ndnSI ...

  7. 《SQL Server 2012 T-SQL基础》读书笔记 - 10.可编程对象

    Chapter 10 Programmable Objects 声明和赋值一个变量: DECLARE @i AS INT; SET @i = 10; 变量可以让你暂时存一个值进去,然后之后再用,作用域 ...

  8. you have not created a boot efi partition

    rhel6.8 自定义分区,创建 /boot/efi 分区找不到”EFI System Partition“文件系统, 选其他文件系统 next时都提示:you have not created a ...

  9. python 调用C++ DLL,传递int,char,char*,数组和多维数组

    ctypes 数据类型和 C数据类型 对照表 ctypes type C type Python type c_bool _Bool bool (1) c_char char 1-character ...

  10. fedora bash shell 为什么不能使用ctrl+c了?

    无法使用ctrl+c? 原来是因为, 在shell中, 为了选择和复制粘贴文字内容的方便, 对shell的快捷键进行了设置, 将复制设置为 ctrl+c了, 将zhantie设置为ctrl+v了 所以 ...