[开心IT面试题] 查找最小的K个元素(数组)

题目:

输入n个整数,输出其中最小的k个。

例如输入1,2,3,4,5,6,7和8这8个数字,则最小的4个数字为1,2,3和4。

 

解法一:

   利用堆排序的小根堆的思想,依次找出最小的数、小第二的数、小第三的数……一直到找出小第K的数。

   此办法找出的最小K个数是有序的。

代码:

void Heapift_Samll(int elem[], int node, int length)
{
    int tempElem = elem[node];
    int leftChild = 2*node+1;
    int rightChild = 2*node+2;
    while(leftChild < length)
    {
        rightChild = 2*node+2;
        if((rightChild < length) && (elem[rightChild] < elem[leftChild]))
        {
            if(elem[rightChild] < tempElem)
            {
                elem[node] = elem[rightChild];
                elem[rightChild] = tempElem;
                node = rightChild;
            }else
            {
                break;
            }
        }else
        {
            if(elem[leftChild] < tempElem)
            {
                elem[node] = elem[leftChild];
                elem[leftChild] = tempElem;
                node = leftChild;
            }else
            {
                break;
            }
        }
        tempElem = elem[node];
        leftChild = 2*node+1;
    }
}

void HeapFindMinElem(int elem[], int elemLen, int *minElem, int minElemLen)
{
    //先把数组建立成小根堆
    for(int i = elemLen/2-1; i >= 0 ; i--)
    {
        Heapift_Samll(elem, i, elemLen);
    }

    int tempElem = 0;//交换数据的中间变量
    for(int j = elemLen-1; j > elemLen-1-minElemLen; j--)
    {
        //将堆首与堆尾交换,
        tempElem = elem[0];
        elem[0] = elem[j];
        elem[j] = tempElem;
        minElem[elemLen-j-1] = tempElem;

        //重新调整小根堆
        Heapift_Samll(elem, 0, j);
    }
}
 
解法二:
   利用快递排序的思想,找出最小的K个数。
   此办法找出的最小K个数是无序的。
代码:
void QuickSort(int elem[], int left, int right, int minElemLen)
{
    int referenceElem = elem[left];//划分数组的参照数
    int pos = left;//记录排序后参照数的位置
    int i = right;//i标记从right位置向前搜索的位置
    int j = left;//j标记从left位置向后搜索的位置

    while(i > j)
    {
        for(; i > j; i--)
        {
            if(elem[i] < referenceElem)
            {
                elem[pos] = elem[i];
                j++;
                pos = i;
                break;
            }
        }

        for(; j < i; j++)
        {
            if(elem[j] > referenceElem)
            {
                elem[pos] = elem[j];
                i--;
                pos = j;
                break;
            }
        }
    }
    elem[pos] = referenceElem;
    PrintfElem(elem, 30);
    if(((pos-left) == minElemLen) || ((pos-left+1) == minElemLen))
    {
        return;
    }else if((pos-left) > minElemLen)
    {
        QuickSort(elem, left, pos-1, minElemLen);
    }else if((pos-left) < minElemLen)
    {
        QuickSort(elem, pos+1, right, minElemLen-(pos-left)-1);
    }
}

void QuickFindMinElem(int elem[], int elemLen, int *minElem, int minElemLen)
{
    if(elem == NULL && elemLen == 0)
    {
        return;
    }
    if(elemLen < minElemLen)
    {
        memcpy(minElem, elem, elemLen*sizeof(int));
        return;
    }

    QuickSort(elem, 0, elemLen-1, minElemLen);
    memcpy(minElem, elem, minElemLen*sizeof(int));
}

快递排序请参考:http://blog.csdn.net/mmoojing/article/details/17690657

 
 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值