求一個無序數組的中位數

求一個無序數組的中位數。

如:{2,5,4,9,3,6,8,7,1}的中位數爲5,{2,5,4,9,3,6,8,7,1,0}的中位數爲4和5。
要求:不能使用排序,時間複雜度儘可低。

實現思路:

解法一:快排思想

【背景知識】
1.快速排序可以實現將數據劃分爲 三部分 : 左邊小於基準值 基準值 右邊大於基準值位置

2.每次劃分都可以將基準值的最終確定, 那這樣的話,我們找中位數就很方便了。
如果劃分返回的區間

  1. 小於mid 去 右區間進行下一步查找
  2. 大於mid 去 左區間進行下一步查找
  3. ==mid 返回

代碼實現:

int PartionMid(int array[], int left ,int right)
{

    int key = array[right];
    int begin = left;
    int end = right;

    while (begin < end)
    {
        while (begin < end&&array[begin] <=key)   //注意是<= 
        {
            begin++;
        }

        while (begin < end&&array[end] >=key)
        {
            end--;
        }

        if (begin < end)
        {
            swap(array[begin],array[end]);
        }
    }
    swap(array[begin], array[right]);
    return begin;

}

//實現思路: 如果下標<mid去左區間找   ,如果下標>mid  去右區間找
int FindMid(int array[], int size)
{

    int mid = (size-1)/ 2;
    int left = 0;
    int right = size - 1;
    int index = 0;

    index = PartionMid(array, left, right);

    while (index != mid)
    {
        if (index < mid)  //去右區間找
        {
            index = PartionMid(array, index+1, right);
        }
        else if (index>mid)//去左區間找
        {
            index = PartionMid(array, left, index-1);
        }
    }
    return array[mid];

}

解法二: TopK問題

求中間大元素:建小堆,每次和當前堆最小值進行比較,
1.如果小於堆頂(當前堆最小值),說明不是 前K個數據,直接過濾掉
2.如果大於堆頂(當前堆最小值),說明有可能是 前K個數據
替換掉堆頂,再次對當前堆頂進行調整,滿足最小堆性質

另外:優先級隊列的底層也是通過建堆來實現的。默認是建大堆,此時就要編寫一個使其建小堆的仿函數了,其實也就是相當於修改了它的優先級。

代碼實現:

//優先級隊列實現 :天然的堆
int GetMidByQue(int arr[], int size)
{

    int mid = (size) / 2+1;  
    struct Com
    {
        bool operator ()(int num1, int num2)
        {
            return num1 > num2;
        }
    };

    priority_queue<int, vector<int>,Com> q;
    for (int i = 0; i < mid; i++)
    {
        q.push(arr[i]);
    }
    for (int i = mid; i < size; i++)
    {
        if (arr[i]>q.top())  //替換掉元素
        {
            q.pop();
            q.push(arr[i]);
        }
    }

    //返回堆頂元素即可


    if (!q.empty())
    {
        return q.top();
    }
    else
    {
        return -111111;
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章