luogu_P1177 【模板】快速排序 (快排和找第k大的数)
【算法】
选取pivot,然后每趟快排用双指针扫描(l,r)区间,交换左指针大于pivot的元素和右指针小于pivot的元素,将区间分成大于pivot和小于pivot的
【注意】
时间复杂度取决于pivot的选取是否能把(l,r)区间分成长度相等的两个子区间。
最优:O(nlogn) 最差:O(n2)
问题解决:
- 版本一: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大的数)的更多相关文章
- 快排法求第k大
快排法求第k大,复杂度为O(n) import com.sun.media.sound.SoftTuning; import java.util.Arrays; import java.util.Ra ...
- 找第k大的数
(找第k大的数) 给定一个长度为1,000,000的无序正整数序列,以及另一个数n(1<=n<=1000000),接下来以类似快速排序的方法找到序列中第n大的数(关于第n大的数:例如序列{ ...
- P1049 找第K大的数
题目描述 给定一个无序正整数序列, 以及另一个数n (1<=n<=1000000), 然后以类似快速排序的方法找到序列中第n大的数(关于第n大的数:例如序列{1,2,3,4,5,6}中第3 ...
- 快速排序算法的实现 && 随机生成区间里的数 && O(n)找第k小 && O(nlogk)找前k大
思路:固定一个数,把这个数放到合法的位置,然后左边的数都是比它小,右边的数都是比它大 固定权值选的是第一个数,或者一个随机数 因为固定的是左端点,所以一开始需要在右端点开始,找一个小于权值的数,从左端 ...
- 找出N个无序数中第K大的数
使用类似快速排序,执行一次快速排序后,每次只选择一部分继续执行快速排序,直到找到第K个大元素为止,此时这个元素在数组位置后面的元素即所求 时间复杂度: 1.若随机选取枢纽,线性期望时间O(N) 2.若 ...
- 找出整数中第k大的数
一 问题描述: 找出 m 个整数中第 k(0<k<m+1)大的整数. 二 举例: 假设有 12 个整数:data[1, 4, -1, -4, 9, 8, 0, 3, -8, 11, 2 ...
- 基于快速排序思想partition查找第K大的数或者第K小的数。
快速排序 下面是之前实现过的快速排序的代码. function quickSort(a,left,right){ if(left==right)return; let key=partition(a, ...
- 寻找第K大的数(快速排序的应用)
有一个整数数组,请你根据快速排序的思路,找出数组中第K大的数.给定一个整数数组a,同时给定它的大小n和要找的K(K在1到n之间),请返回第K大的数,保证答案存在.测试样例:[1,3,5,2,2],5, ...
- 算法题之找出数组里第K大的数
问题:找出一个数组里面前K个最大数. 解法一(直接解法): 对数组用快速排序,然后直接挑出第k大的数.这种方法的时间复杂度是O(Nlog(N)).N为原数组长度. 这个解法含有很多冗余,因为把整个数组 ...
随机推荐
- connect to SQL Server in python on centos
在centos 6.5 下python使用pyodbc连接sql server 报错: [unixODBC][Driver Manager]Can't open lib 'SQL Server'... ...
- CCF201412-2 Z字形扫描 java(100分)
试题编号: 201412-2 试题名称: Z字形扫描 时间限制: 2.0s 内存限制: 256.0MB 问题描述: 问题描述 在图像编码的算法中,需要将一个给定的方形矩阵进行Z字形扫描(Zigzag ...
- 利用Django框架实现分页 demo
- 前端node面试题之---对比JS和NodeJS的区别
区别: 1.JS运行在浏览器端,用于用户的交互效果,NodeJS运行在服务器端,用于服务器的操作,例如,Web服务器创建,数据库的操作,文件的操作等 2.JS运行在浏览器端,存在多个JS解释器,存在兼 ...
- Bellman-ford算法、SPFA算法求解最短路模板
Bellman-ford 算法适用于含有负权边的最短路求解,复杂度是O( VE ),其原理是依次对每条边进行松弛操作,重复这个操作E-1次后则一定得到最短路,如果还能继续松弛,则有负环.这是因为最长的 ...
- Altera培训SignalTap II的使用--笔记
培训的内容有点多(啰嗦)(笔记为截图) 听课笔记:Altera培训SignalTap II的使用--笔记
- 【BZOJ2200】道路和航线(并查集,拓扑排序,最短路)
题意:n个点,有m1条双向边,m2条单向边,双向边边长非负,单向边可能为负 保证如果有一条从x到y的单项边,则不可能存在从y到x的路径 问从S出发到其他所有点的最短路 n<=25000,n1,m ...
- 设计模式学习笔记——Visitor 访问者模式
1.定义IVisitor接口,确定变化所涉及的方法 2.封装变化类.实现IVisitor接口 3.在实体类的变化方法中传入IVisitor接口,由接口确定使用哪一种变化来实现(封装变化) 4.在使用时 ...
- $FFT/NTT/FWT$题单&简要题解
打算写一个多项式总结. 虽然自己菜得太真实了. 好像四级标题太小了,下次写博客的时候再考虑一下. 模板 \(FFT\)模板 #include <iostream> #include < ...
- D. White Lines
D. White Lines 给定一个$n\times n$的$WB$矩阵,给定一个$k*k$的能把$B$变成$W$的橡皮擦,求橡皮擦作用一次后,全为$W$的行.列总数最大值 前缀和差分 #inclu ...