找到一组数字中,第k小的数字
这个题目是:给定一个数组,找到数组中任意第k小的数字。看完这个题目,我想到的就是我把这个数组,进行排序。这时候我们想要第几小就可以得到第几小了哈,是不是很方便。
在选择的排序算法的时候我们尽量选择堆排序和选择排序,为什么呢?因为这两个排序算法,我们不需要将整个数组排序完,我们只需要将需要查找的排序出来就可以了。
但是这种方法肯定是费时的,我们可以用分治的思想去做,结合快排的一次划分来缩小规模。
对于快排的一次划分,我们可以将基准的这个数字放进数组中,他所在的位置,也就是说前面的数据都是他小,后面的数据都比他大。换句话说它的下标就是他在数组中的第几小,这样我们就可以扔掉一部分规模,依次来找到元素中的第几小。
这里我们列举了一部分,我们只需要将得到的值,如果大于需要的就在左边找,小于就在右边找。
template<class Type>
int Partition(Type *ar, int left, int right)
{
int i = left, j = right;
Type tmp = ar[i];
while (i < j)
{
while (i<j && ar[j] > tmp) --j;
if (i<j) ar[i] = ar[j];
while (i<j && ar[i] <= tmp) ++i;
if (i<j) ar[j] = ar[i];
}
ar[i] = tmp;
return i;
}
template<class Type>
const Type & Select_K(Type *ar,int left,int right,int k)
{
if(left == right && k == 1) return ar[left];
int index = Partition(ar, left, right);
int pos = index - left + 1;
if(k <= pos) return Select_K(ar,left,index,k);
else return Select_K(ar,index+1,right,k-pos);
}
template<class Type>
const Type & Select_K_Min(Type *ar,int n, int k)
{
assert(ar != NULL && n > 0 && k>=1 && k <= n);
return Select_K(ar,0,n-1,k);
}
但是有一个问题就是,我们在这里面不能有重复的数字,如果有重复数字,划分就会有问题,造成死循环。
在这里我们就又遇到了这样的一个题,在一个数组中,我们找到差值最小的值;
如在数组:56,23,12,84,92,28,38,32,100,45,67,78,14;这个值就是2。
这里我们也用到了分治的思想,吧一个数组分成两个部分,左边找间隔最小的,右边找间隔最小的,还有分隔的这部分,然后三个里面最小的。
这样我们就可以吧数组缩小,然后到最后剩下两个值的时候,可以算出来。
template<class Type>
int Partition(Type *ar, int left, int right)
{
int i = left, j = right;
Type tmp = ar[i]; //
while (i < j)
{
while (i<j && ar[j] > tmp) --j;
if (i<j) ar[i] = ar[j];
while (i<j && ar[i] <= tmp) ++i;
if (i<j) ar[j] = ar[i];
}
ar[i] = tmp;
return i;
}
template<class Type>
const Type & Select_K(Type *ar,int left,int right,int k)
{
if(left == right && k == 1) return ar[left];
int index = Partition(ar, left, right);
int pos = index - left + 1;
if(k <= pos) return Select_K(ar,left,index,k);
else return Select_K(ar,index+1,right,k-pos);
}
template<class Type>
const Type & Select_K_Min(Type *ar,int n, int k)
{
assert(ar != NULL && n > 0 && k>=1 && k <= n);
return Select_K(ar,0,n-1,k);
}
int MaxS1(int *br,int left,int right)
{
return br[right];
}
int MinS2(int *br,int left,int right)
{
int min = br[left];
for(int i =left + 1; i<=right; ++i)
{
if(min > br[i])
{
min = br[i];
}
}
return min;
}
int Min3d(int a,int b,int c)
{
return a < (b < c ? b : c) ? a : (b < c ? b : c);
}
int Cpair_min(int *br,int left,int right)
{
if(right - left <= 0) return INT_MAX;
int k = (right - left + 1)/2;
int index = k + left - 1;
Select_K(br,left,right,k);
int mind1 = Cpair_min(br,left,index);
int mind2 = Cpair_min(br,index+1,right);
int smax = MaxS1(br,left,index);
int smin = MinS2(br,index+1,right);
return Min3d(mind1,mind2,smin-smax);
}
int Cpair_ar(int *br,int n)
{
if(NULL == br || n < 2) return INT_MAX;
return Cpair_min(br,0,n-1);
}