题目:
——给出n个数,从小到大排序,并输出
牛客例题1
牛客例题2
例题3:求第k大,并输出
啊哈一书快排思想:(分好区间后选定的哨兵位置可以确定)
二分思想:
先对大区间进行排序,并不是真正意义上的排好序:
1. 以大区间第一个数为哨兵,实现以下操作:
a. 比它小的通通放到左边,比它大的通通放到右边
b. 并不要求哨兵的左右各部分必须是有序的
如何实现操作a,遍历交换即可
c. 需要两个指针i,j,最初指向区间的最左、最右端
让 j 从位置 j 往左找,找到比哨兵小的数,停下。
接着让 i 从位置 i 往右找,找到比哨兵大的数,停下。
若i 此刻小于 j,交换位置上的值,目的是小的站左边,大的站右边
反反复复进行此操作,直至 i 与 j 碰头
d. 此刻哨兵站在区间首位,哨兵后面的已经分好了2队,左队和右队,
此刻只需左队最后的一个位置与哨兵交换,即可实现哨兵左边都比哨兵小,哨兵右边都比哨兵大。
2. 大区间完成后,可发现哨兵改变了位置,把大区间分为了两个小区间,接着再进行操作 1
代码:
#include<stdio.h>
int a[110000];
void swap(int i,int j)
{
a[i]^=a[j];
a[j]^=a[i];
a[i]^=a[j];
}
void quickSort(int l,int r)
{
if(l>=r) return;
int i=l,j=r,temp=a[l];
while(i<j)
{
//两个while位置不能交换,不然试试代码下面的样例
while(a[j]>=temp&&i<j)
j--;
while(a[i]<=temp&&i<j)
i++;
if(i<j)
swap(i,j);
}
//下面两行很关键:确定了哨兵的最后位置
a[l]=a[i];
a[i]=temp;
quickSort(l,i-1);
quickSort(i+1,r);
}
int main()
{
int n;
while(~scanf("%d",&n))
{
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
quickSort(1,n);
for(int i=1;i<=n;i++)
{
if(i!=1) printf(" ");
printf("%d",a[i]);
}
printf("\n");
}
return 0;
}
n特别大过不了,但确实就是快排思想
不超时的代码网上有,但我感觉这个比较理解,
可以确定每次哨兵的位置,不用管边界问题。
样例
5 3
2 4 1 5 3
代码:
//第k大算法
//这种不知道算不算二分思想,先这样写吧
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int a[N],kk;
void quickSort(int l,int r)
{
if(l>=r) return;
int i=l,j=r,temp=a[l];
while(i<j)
{
while(a[j]>=temp&&i<j) j--;
while(a[i]<=temp&&i<j) i++;
if(i<j) swap(a[i],a[j]);
}
a[l]=a[i];
a[i]=temp;
if(kk<=i)
quickSort(l,i-1);
else
quickSort(i+1,r);
}
int main()
{
int n,i;
scanf("%d %d",&n,&kk);
for(i=1;i<=n;i++)
scanf("%d",&a[i]);
quickSort(1,n);
printf("%d\n",a[kk]);
return 0;
}