线性时间内从一个数组中找出第K个最小的元素——编程珠玑
2012-08-28 16:27
369 查看
线性时间内从一个数组中找出第K个最小的元素——编程珠玑
题目:编写程序,在O(n)时间内从数组x[0...n-1]中找出第k个最小的元素,算法中可以对x中的元素进行排序。
算法实现一:
#include<iostream>
using namespace std;
inline void Swap(int a[],int i,int j)//内联函数,交换两个元素位置
{
int temp=a[i];
a[i]=a[j];
a[j]=temp;
}
int Partition(int a[],int p,int r)//根据pivot a[r]来划分数组
{
int pivot=a[r];
int low=p-1;
int i;
for(i=p;i<r;i++)
{
if(a[i]<=pivot)
Swap(a,++low,i);
}
Swap(a,++low,r);
return low;
}
int RondomPartition(int a[],int p,int r)
{
int i=p+rand()%(r-p+1);//随机选择一个pivot来划分
Swap(a,i,r);
return Partition(a,p,r);//返回轴位置
}
int SelectKMin(int a[],int p,int r,int k)
{
if(p==r)
return a[p];
int q=RondomPartition(a,p,r);
int count=q-p+1;//计算 a[p..q]的元素数量
if(k==count)//刚好,返回
return a[q];
else if(k<count)//在前半部分
return SelectKMin(a,p,q-1,k);
else //在后半部分
return SelectKMin(a,q+1,r,k-count);
}
int main()
{
int a[]={2,3,4,1,5,10,9,7,8,6};
int k=3;
cout<<SelectKMin(a,0,9,k)<<endl;
return 0;
}
算法实现二:
#include"stdio.h"
int GetMinK(int A[],int n,int k)
{
int s=-1,i=0,j=n-1,temp;
int beg=i;
int end=j;
while(s!=k)
{
beg=i;
end=j;
temp=A[i];
while(i<j)
{
while(i<j&&A[j]>=temp)j--;A[i]=A[j];
while(i<j&&A[i]<=temp)i++;A[j]=A[i];
}
A[i]=temp;
s=i;
if(s==k)
return A[k];
if(s>k){i=beg;j--;} //在左侧寻找
if(s<k){j=end;i++;} //在右侧寻找
}
}
int main()
{
int A[]={2,3,4,1,5,10,9,7,8,6};
int k=3;
printf("第%d小元素为:(从0开始)\n%d ",k,GetMinK(A,10,k));
return 0;
}
题目:编写程序,在O(n)时间内从数组x[0...n-1]中找出第k个最小的元素,算法中可以对x中的元素进行排序。
思路:快速排序选择一个pivot对数组进行划分,左边小于pivot,右边大于等于pivot,所以我们计算左边小于pivot(加上pivot)的个数count总共有多少,如果等于k,正是我们所要的,如果大于k,说明第k小的数在左边,那就在左边进行我们的递归;否则,在右边,那么说明右边的第k-count小的数就是我们所要的,在右边进行我们的递归。
算法实现一:
#include<iostream>
using namespace std;
inline void Swap(int a[],int i,int j)//内联函数,交换两个元素位置
{
int temp=a[i];
a[i]=a[j];
a[j]=temp;
}
int Partition(int a[],int p,int r)//根据pivot a[r]来划分数组
{
int pivot=a[r];
int low=p-1;
int i;
for(i=p;i<r;i++)
{
if(a[i]<=pivot)
Swap(a,++low,i);
}
Swap(a,++low,r);
return low;
}
int RondomPartition(int a[],int p,int r)
{
int i=p+rand()%(r-p+1);//随机选择一个pivot来划分
Swap(a,i,r);
return Partition(a,p,r);//返回轴位置
}
int SelectKMin(int a[],int p,int r,int k)
{
if(p==r)
return a[p];
int q=RondomPartition(a,p,r);
int count=q-p+1;//计算 a[p..q]的元素数量
if(k==count)//刚好,返回
return a[q];
else if(k<count)//在前半部分
return SelectKMin(a,p,q-1,k);
else //在后半部分
return SelectKMin(a,q+1,r,k-count);
}
int main()
{
int a[]={2,3,4,1,5,10,9,7,8,6};
int k=3;
cout<<SelectKMin(a,0,9,k)<<endl;
return 0;
}
算法实现二:
#include"stdio.h"
int GetMinK(int A[],int n,int k)
{
int s=-1,i=0,j=n-1,temp;
int beg=i;
int end=j;
while(s!=k)
{
beg=i;
end=j;
temp=A[i];
while(i<j)
{
while(i<j&&A[j]>=temp)j--;A[i]=A[j];
while(i<j&&A[i]<=temp)i++;A[j]=A[i];
}
A[i]=temp;
s=i;
if(s==k)
return A[k];
if(s>k){i=beg;j--;} //在左侧寻找
if(s<k){j=end;i++;} //在右侧寻找
}
}
int main()
{
int A[]={2,3,4,1,5,10,9,7,8,6};
int k=3;
printf("第%d小元素为:(从0开始)\n%d ",k,GetMinK(A,10,k));
return 0;
}
相关文章推荐
- 线性时间内从一个数组中找出第K个最小的元素
- 编写程序,在O(n)时间内从数组x[0..n-1]中找出第k个最小的元素?
- 在线性级别时间内找出无序序列中的第k个元素
- 整数数组中,每个元素均出现两次,除了一个元素例外,如何找出这个元素?能否设计一个线性时间的算法,且不需要额外的存储空间?
- 用线性时间复杂度实现找出数组中出现一次的元素
- 用线性时间复杂度实现找出数组中出现一次的元素
- 用线性时间复杂度实现找出数组中出现一次的元素
- 用线性时间复杂度实现找出数组中出现一次的元素
- 用线性时间复杂度实现找出数组中出现一次的元素
- 线性时间内查找第k个最小数
- 面试题精选(85):给定数组Arr[n],O(n)时间内找出每个元素左侧所有元素中位置最靠近该元素且大于该元素的元素
- 从一个数组中找出第k小元素的随机化算法 c语言实现 算法导论第九章
- 在O(n)时间内找出最小的k个元素
- 主元素问题(判断数组是否出现主元素,O(n)时间内找出主元素,主元素出现次数)
- 给定数组Arr[n],O(n)时间内找出每个元素左侧所有元素中位置最靠近该元素且大于该元素的元素
- 剑指offer--找出旋转数组中的最小元素
- 给定数组Arr[n],O(n)时间内找出每个元素左侧所有元素中位置最靠近该元素且大于该元素的元素
- 取值为[1,n-1] 含n 个元素的整数数组至少存在一个重复数,O(n) 时间内找出其中任意一个重复数
- 从一个数据元素无序的整型数组中找出最小的两个数的下标
- 一个整数数组,每个数字都出现K次,只有一个数字出现M次,找出这个数字(线性时间)