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源创计划”,欢迎正在阅读的你也加入,一块儿分享。

相关文章
相关标签/搜索