学习目标:快速排序之第k大数
从今天开始搞算法,一天一个,第二天,强行flag
学习内容:
- 对于数组,借用快排的轴判断,k位于哪个区间
- 对此区间数组进行重复操作
- 退出条件为begin==end
学习时间:
提示:大概用时
1、 21/2/23周一 晚上 7 点—晚上9点
kthLargest code:
#include<stdio.h>
#include <stdlib.h>
#include <time.h>
void swap(int arr[],int j,int k)
{
if(j==k) return; // 同一元素时则不交换
int temp;
temp=arr[j];
arr[j]=arr[k];
arr[k]=temp;
printf("swap %d and %d\n",arr[j],arr[k]);
}
int randompartition(int arr[],int begin,int end)
{
int a;
srand((unsigned)time(NULL));
a = rand()%(end-begin)+begin;
//printf(" a=%d ",a);
swap(arr,a,begin);//除去以上即为正常快速排序
int first = arr[begin];
int i = begin+1,p=begin;
for(i;i<=end;i++)
{
if(first<arr[i]) // 逆序 从大到小
{
p++;
swap(arr,p,i);
}
}
swap(arr,p,begin);
printf("one time %d \n",p);
return p;
}
// 第k大数,是从大到小排序后,正数第k个数
int randomselect(int arr[],int begin,int end,int aim)
{
int i,j;
if(begin==end) return arr[begin];
i = randompartition(arr,begin,end);
j=i-begin+1; // 得到以轴分开的数组左侧长度,判断左侧长度(含轴)与目标位置aim是否包含,舍弃另一半
if(aim>j)
randomselect(arr,i+1,end,aim-j);
else
randomselect(arr,begin,i,aim);
}
int main()
{
int Len,i,aim;
while(scanf("%d",&Len)!=EOF)
{
int nums[Len];
for(i=0;i<Len;i++)
{
scanf("%d",&nums[i]);
}
scanf("%d",&aim);
printf("%d\n",randomselect(nums,0,Len-1,aim));
}
return 0;
}
最后自己再来总结一下,这个和二分法有异曲同工之妙,但是快排明显随机性更高巧妙性更高,随机选取轴,选取区间,对于区间再快排选取轴,以此来达到选取第k大数,不需要排序是相当舒服了