选择第n大的数
借鉴快速排序算法,返回每趟确定的一个元素的位置,与n比较。在快速排序中使用随机生成的枢轴,如果数据排列均匀,也可以选第一个数作为枢轴。
//
// Created by dgm on 2020/1/3.
//
#include <iostream>
#include <time.h>
#include <stdlib.h>
using namespace std;
int n;
int *a;
int k;
int partation(int left,int right){
int pos=(int)(1.0*rand()/RAND_MAX*(right-left)+left);//随机生成枢轴
swap(a[pos],a[left]);
int temp=a[left];
while(left<right){ //因为是选第n大的数,所以将a按从大到小排序
while(left<right&&a[right]<temp)right--;
a[left]=a[right];
while(left<right&&a[left]>=temp)left++;
a[right]=a[left];
}
a[left]=temp;
return left; //返回枢轴元素的最终位置
}
void selectNum(int left,int right,int K){
if(left<right){
int pos=partation(left,right);
if(pos+1==K){
printf("%d\n",a[pos]);
return;
}else if(pos+1<K){
selectNum(pos+1,right,K);
}else{
selectNum(left,pos-1,K);
}
}
}
int main(){
srand((unsigned)time(NULL));
scanf("%d",&n);
scanf("%d",&k);
a=(int *)malloc(n* sizeof(int));
for (int i = 0; i < n; ++i) {
scanf("%d",a+i);
}
selectNum(0,n-1,k);
return 0;
}
一个应用:
将一个整数集合S划分为两个子集S1和S2,分别含有n1和n2个元素,S1与S2的并为S,交为空。要求:在|n1-n2|尽可能小的条件下,使S1元素的和与S2元素的和的差的绝对值即|S1-S2|尽可能大。
以前的做法:将S排序,求前一半和后一半的差。
现在的做法:如果枢轴元素恰好在中间位置,将枢轴元素及之前和之后的元素分别求和,然后作差取绝对值。
//
// Created by dgm on 2020/1/3.
//
#include <iostream>
#include <time.h>
#include <stdlib.h>
using namespace std;
int n;
int *a;
int res=0;
int partation(int left,int right){
int pos=(int)(1.0*rand()/RAND_MAX*(right-left)+left);
swap(a[left],a[pos]);
int temp=a[left];
while(left<right){
while(left<right&&a[right]>temp)right--;
a[left]=a[right];
while(left<right&&a[left]<=temp)left++;
a[right]=a[left];
}
a[left]=temp;
return left;
}
int maxAbs(int left,int right){
if(left<right){
int pos=partation(left,right);
if(pos==n/2-1){
for (int i = 0; i <= pos; ++i) {
res+=abs(a[i]-a[pos+1+i]);
}
if(n%2==1)res+=abs(a[n-1]); //如果有奇数个元素,则两个集合元素数目相差一
return res;
}else if(pos<n/2-1){
maxAbs(pos+1,right);
}else{
maxAbs(left,pos-1);
}
}
}
int main(){
srand((unsigned)time(NULL));
scanf("%d",&n);
a=(int *)malloc(n* sizeof(int));
for (int i = 0; i < n; ++i) {
scanf("%d",a+i);
}
printf("%d\n",maxAbs(0,n-1));
return 0;
}