golang刷leetcode 技巧(47)無序數組的中位數

要解決這個問題首先要了解什仫是中位數,所謂的中位數就是在一組有序的數字中找到中間的那個數字。若是數字的個數是奇數則直接返回中間的那個數,若是數字的個數是偶數此時這組數據的中位數有兩個,取中間兩個數的平均值便可。php

想法1、不論用什仫排序算法使得該組數據有序,直接取中間值便可。golang

這種只要你掌握常見的排序算法就能夠了,在這裏就不實現了。算法

想法2、利用快排的思想數組

一、先進行一趟快排,使得div左邊的值都比arr[div]小,div右邊的值都比arr[div]大,可是這個div的位置是不肯定的,可能位於中間,也可能偏左或者偏右。微信

二、計算出mid所在的下標,若是是奇數則是mid=(size+1)/2,若是是偶數則是mid=size/2。架構

三、此時須要比較mid和div所在的位置。若是mid在div所在位置的左邊,此時就要遞歸去左半區間查找;若是mid在div的右邊,此時就要遞歸去右半區間查找;若是剛好相等則說明div/mid所在的位置就是中位數。函數

代碼實現以下:.net


int PartSort(int *arr, int start, int end)code

{排序

    int left = start;

    int right = end;

    int key = arr[end];   //選取關鍵字

    while (left < right)

    {

        while (left < right && arr[left] <= key)  //左邊找比key大的值

        {

            ++left;

        }

        while (left < right && arr[right] >= key)  //右邊找比key小的值

        {

            --right;

        }

        if (left < right)

        {

            swap(arr[left], arr[right]);  //找到以後交換左右的值

        }

    }

    swap(arr[right], arr[end]);

    return left;

}

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

int GetMidNumNoSort1(int *arr,int size)

{

    assert(arr);

    int start = 0;

    int end = size - 1;

    int mid = (size - 1) / 2;

    int div = PartSort(arr,start,end);

    while (div != mid)

    {

        if (mid < div)   //左半區間找

            div = PartSort(arr, start, div - 1);

        else    //左半區間找

            div = PartSort(arr, div + 1, end);

    }

    return arr[mid];   //找到了

}


想法3、建堆的思想


一、若是數組元素的個數是奇數,取數組前(size+1)/2個元素建堆,若是是偶數則取前 size/2 個元素建堆。

二、建完堆以後,此時堆頂的元素是這前 (size-1)/2 個元素中最小的;此時須要將數組中剩餘的元素分別和堆頂的元素進行比較:若是小於等於堆頂元素則直接丟棄,若是大於堆頂的元素則須要更新堆頂的元素並從新調整堆的結構,使其保證小頂堆的特性。

三、將剩餘的元素所有比較完以後,此時堆頂的元素就是所要求的中位數。

在這裏須要提到的是,優先級隊列的底層也是經過建堆來實現的。默認是建大堆,此時就要編寫一個使其建小堆的仿函數了,其實也就是至關於修改了它的優先級。

代碼實現以下:


//建小堆來實現

#include<queue>

#include<vector>

int GetMidNumNoSort2(int *arr, int size)

{

    assert(arr);

    int len = (size + 1) / 2;   //奇數個元素

    //int len = size / 2;

    struct Compare    //建小堆

    {

        int operator()(int left, int right)

        {

            return left > right;

        }

    };

    priority_queue<int, vector<int>, Compare> heap;

    //先以整個數組的前len個元素建小堆

    for (int i = 0; i < len; i++)

    {

        heap.push(arr[i]);

    }

    for (int i = len; i < size; i++)

    {

        if (arr[i] > heap.top())  //比堆頂元素大則更新該小堆

        {

            heap.pop();

            heap.push(arr[i]);

        }

    }

    if (!heap.empty())

    {

        return heap.top();

    }

}


本文分享自微信公衆號 - golang算法架構leetcode技術php(golangLeetcode)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。

相關文章
相關標籤/搜索