1. 程式人生 > 實用技巧 >面試題41:資料中的中位數

面試題41:資料中的中位數

如何得到一個數據流中的中位數?如果從資料流中讀出奇數個數值,那麼中位數就是所有數值排序之後位於中間的數值。如果從資料流中讀出偶數個數值,那麼中位數就是所有數值排序之後中間兩個數的平均值。我們使用Insert()方法讀取資料流,使用GetMedian()方法獲取當前讀取資料的中位數。

下次一定記住不要再用cout,cin。。。。。。

解題思路

  • 插入到沒排序的陣列

  • 插入到排序的陣列

  • 插入到排序的連結串列

  • 插入到二叉搜尋樹

  • 插入到平衡樹(比較難實現,比如紅黑樹)

  • 插入到堆(效率最高O(logn)、O(1),比較難實現)

上程式碼(C++香)

插入並排序O(logn),查詢中位數O(1)
#include <iostream>
#include <algorithm>
#include <math.h>
#include <cstring>
#include "ListNode.h"
#include "TreeNode.h"
#include "Graph.h"
using namespace std;

#define MAXNUM 100010
#define DRIFT 1001

vector<int> numbers;

void mySwap(vector<int> &num, int i, int j){
    int temp = num[j];
    num[j] = num[i];
    num[i] = temp;
}

int myPartition(vector<int> &num, int low, int high){
    int pivot = num[low];
    while(low < high){
        // 將右邊比pivot小的放到左邊
        while(low < high && num[high] >= pivot)
            high--;
        mySwap(num, low, high);
        while(low < high && num[low] <= pivot)
            low++;
        mySwap(num, low, high);
    }
    return low;
}

// 快排
void QSort(vector<int> &num, int low, int high){
    if(low >= high)
        return ;
    int pivot = myPartition(num, low, high);
    QSort(num, low, pivot - 1);
    QSort(num, pivot + 1, high);
}

// 插入到排序的陣列中
void Insert(int num){
    numbers.push_back(num);
    QSort(numbers, 0, numbers.size() - 1);
}

// 獲取中位數
double GetMedian(){
    int length = numbers.size();
    if(length == 0)
        return 0.0;

    double ans = 0.0;
    // 奇數
    if(length % 2)
        ans = (double)numbers[length/2];
    // 偶數
    else
        ans = (double)numbers[length/2-1] + ((double)(numbers[length/2] - numbers[length/2-1])) / 2;

    return ans;
}

int main()
{
    Insert(1);
    Insert(2);
    Insert(3);
    Insert(4);
    Insert(5);
    Insert(6);
    cout<<GetMedian();
    return 0;
}