小范围排序(C++)


1、小范围排序
已知一个几乎有序的数组,几乎有序是指,如果把数组排好顺序的话,每个元素移动的距离可以不超过k,并且k相对于数组来说比较小。
选择改进的堆排序。根据题意,最小值一定在A的前k(0~k-1)个元素内、次小值一定在A的第二组k(1~k)个元素内,以此类推,每次取原数组A的k个元素进行堆排序,然后把堆顶元素放入A的已排序序列中,(0~k-1)排序的堆顶赋值给A[0],(1~k)排序的堆顶赋值给A[1],以此类推。最后剩下A中最后的k个元素(k-n~n-1),进行标准的堆排序,第一次是K个元素的堆,排序后将堆顶赋值给A[n-k],紧接着把堆尾元素赋值给堆顶,再排序,此时只是k-1个元素的堆,依次类推,每次把堆顶元素放入A中已排序序列后,都把堆尾元素赋值到堆顶,同时堆的元素个数减1,直到堆的元素个数为1,整个排序结束。
class  ScaleSort {
public
:
void  heapify( int * B, int  i, int  k) {
         int  j,ex;
        ex = B[i];
        j = 2*i + 1;
         while  (j < k) {
            if (j + 1 < k && B[j + 1] < B[j]) 
                j++;            
            if (B[j] >= ex)  break ;           
            B[i] = B[j];
            i = j;
            j = 2*i + 1;
        }
        B[i] = ex;
         return ;
    }

     vector <int> sortElement( vector < int > A,  int  n,  int  k) {
        // write code here
         int  m = 0,exc;
        int  *temp =  new
        int [k];
         for  ( int  l = 0;l < k;l++) {
            temp[l] = A[l];
        }
         for  ( int  i = k/2-1;i >= 0;i--)
        heapify(temp,i,k);

         for  ( int  i = k;i < n;i++) {
            A[i-k] = temp[0];
            temp[0] = A[i];
            heapify(temp,0,k);
        }

         for  ( int  j = n-k;j < n;j++) {
            A[j] = temp[0];
            k--;
            temp[0] = temp[k];
            heapify(temp,0,k);
        }

         delete  []temp;
        temp = NULL;
         return  A;
    }
};

2、求一个数组排序后相邻元素之差的最大值,时间复杂度为O(n)、空间复杂度为O(n)
若先排序后求差值则只有桶排序满足时间复杂度,但是桶排序不能满足空间复杂度,桶排序的空间复杂度为O(max-min)。因此要用改进的桶排序但是又没有真正的排序。

①、求出数组A的最大值max和最小值min,并把区间max-min平均分成n份,每份大小为interval,则只需要n+1个桶;
②、用A[i]-min/interval的整数部分确定A[i]该入的桶,并定义三个大小为n+1的数组,bucket记录n+1个桶每个桶的入桶元素个数,max_bucket记录每个桶中最大值,min_bucket记录每个桶中最小值;
③、遍历bucket数组,将后一个桶的最小值min_bucket[j]减去前一个桶的最大值max_bucket[j-1],记录下最大的差值,返回该差值。

class  Gap {
public :
     int  maxGap( vector < int > A,  int  n) {
         int  max = A[0],min = A[0];

        for ( int  i = 1;i < n;i++) {
            if (A[i] > max) max = A[i];
            else
                if (A[i] < min) min = A[i];
        }

         float  interval = ( float )(max - min)/n;

         int  bucket[n+1];
        for ( int  j = 0;j < n+1;j++) 
            bucket[j] = 0;

        
int  max_bucket[n+1],min_bucket[n+1];

        for ( int  i = 0;i < n;i++) {
             int  j = ( int )(A[i]-min)/interval;
            bucket[j]++;
            min_bucket[j] = A[i];
            max_bucket[j] = A[i];
        }

        for ( int  i = 0;i < n;i++) {
             int  j = ( int )(A[i]-min)/interval;
            if (A[i] > max_bucket[j]) max_bucket[j] = A[i]; 
            if (A[i] < min_bucket[j]) min_bucket[j] = A[i];
        }

         int  maxGap = 0;
        for ( int  i = 0,j = 1;j < n+1;j++) {
            if (bucket[j] > 0) {
                if (min_bucket[j]-max_bucket[i] > maxGap) 
                    maxGap = min_bucket[j] - max_bucket[i];
                i = j;
            }                
        }
         return  maxGap;
    }
};
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值