博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
中位数的求法
阅读量:5079 次
发布时间:2019-06-12

本文共 3670 字,大约阅读时间需要 12 分钟。

  前段时间面试遇到一个小题 把我难住了,题目是数组中有N个正整数,数组存储是无序的,求数组的中位数。当时没想出好的办法 ,在离开后,到了地铁上,我想到一个办法。可以快速解决问题。之前没有研究过这个问题,这个方法全凭我用脑子想出来的。希望大家能提出更好的办法或者建议。

  假如数组中的每个正整数是四字节类型的,则数组的大小范围是 0x 00 00 00 00 到 0x 7F FF FF FF。我们一般最先想到的办法 就是采用排序的方法将数组排序,排序后位于数组 N / 2 位置的数即中位数。(这里我们为了简便,不考虑N是奇数还是偶数,如果是奇数,那就是N/2位置的数,如果是偶数,则是N/2 和 N/2+1位置上的两个数的平均值。)采用排序的办法 ,时间复杂度最少为O(NlogN),太慢。

  我想到的方法时间复杂度是O(N)。思路是这样的:

(1)建立一个256的统计数组(记为hist),全部置0,统计原始数组(记为array)元素最高字节的出现的次数;

(2)然后对统计数组进行遍历,找到中值所处的位置,记为mid,则hist[0]到hist[mid-1]的总和记为num_left, hist[mid+1]到hist[255]的总和记为num_right,则

  num_left + num_right + hist[mid] = N,并且 num_left <= N/2 和 num_right <= N/2

(3)对原始数组中最高字节为mid值的所有元素的次高字节进行统计,再找出新的中值,将中值左边的总数加到num_left中,将中值d右边的总数加到num_right,以此类推,直到找到最低字节。

 

下面看源代码,源代码中焉整数的范围只是0x 00 00 到 0x FF FF ,主要是为了简单阐述我的思路。

/*问题:求正整数数组中的中值。正整数的范围是0 到 0xFF FF思路:    (1)先对最高字节通过256的直方图求中值,并统计出中值左右两边分别的数量    (2)求(1)求得的中值,再只对数组中所有最高字节等于中值的元素,求次高元素的中值    (3)以此类推 */#include "stdafx.h"#include 
#include
#include
#include
//数组的大小#define N 10001//打印数组内容void print(int* arr, int len);//求中值int GetMidNum(int* arr, int len);//冒泡排序void sort_bubble(int* arr, int len);int _tmain(int argc, _TCHAR* argv[]){ int *arr = new int[N]; //产生随机数 srand((unsigned int)time(NULL));//initialize random seed; for (int i = 0; i < N; i++) { int a = rand() % 256; int b = rand() % 256; arr[i] = a + (b << 8); } //print(arr, N); //求中值 clock_t t1 = clock(); int midNum = GetMidNum(arr, N); clock_t t2 = clock(); printf("求中值的结果:%x 时间:%d\n", midNum, (t2 - t1) ); //通过排序,求中值,检测上述方法的结果是否正确 clock_t t3 = clock(); sort_bubble(arr, N); clock_t t4 = clock(); printf("排序得中值为:%x 时间:%d\n", arr[N / 2], (t4 - t3) ); //print(arr, N); delete []arr; system("pause\n"); return 0;}void print(int* arr, int len){ printf("\nprint start\n"); for (int i = 0; i < len; i++) { printf("%4x ", arr[i]); if (i % 10 == 9) { printf("\n"); } } printf("\nprint end \n");}int GetMidNum(int* arr, int len){ const int HIST_NUM = 256; int *hist = new int[HIST_NUM]; memset(hist, 0, sizeof(int) * HIST_NUM); //求中值 int midNum = 0; int num_left = 0; int num_right = 0; //统计最高位字节, for (int i = 0; i < len; i++) { hist[ arr[i] >> 8 ]++; } //累积直方图 for (int i = 1; i < HIST_NUM; i++) { hist[i] += hist[i - 1]; } //求高位中值 for (int i = 0; i < HIST_NUM; i++) { if (hist[i] - 1 >= len / 2) { midNum = i; num_left = hist[i - 1]; num_right = len - hist[i]; break; } } memset(hist, 0, sizeof(int) * HIST_NUM); //统计最低位字节, for (int i = 0; i < len; i++) { //printf("%2x %2x \n", arr[i], arr[i] >> 8); if ( (arr[i] >> 8) == midNum) { hist[ (arr[i] & 0xFF) ]++; } } int midNum2 = 0; for (int i = 0; i < HIST_NUM; i++) { num_left += hist[i]; if (num_left - 1 >= len / 2 ) { midNum2 = i; break; } } midNum = midNum << 8; midNum += midNum2; delete []hist; return midNum;}void sort_bubble(int* arr, int len){ for (int i = 0; i < len; i++) { int flag = i; for (int j = flag + 1; j < len; j++) { if (arr[j] < arr[flag]) { flag = j; } } if ( i != flag ) { int temp = arr[i]; arr[i] = arr[flag]; arr[flag]= temp; } }}

 

   

 

转载于:https://www.cnblogs.com/sdlypyzq/p/3321052.html

你可能感兴趣的文章
ionic2+ 基础
查看>>
互联网模式下我们更加应该“专注”
查看>>
myeclipse集成jdk、tomcat8、maven、svn
查看>>
查询消除重复行
查看>>
Win 10 文件浏览器无法打开
查看>>
HDU 1212 Big Number(C++ 大数取模)(java 大数类运用)
查看>>
-bash: xx: command not found 在有yum源情况下处理
查看>>
[leetcode]Minimum Path Sum
查看>>
内存管理 浅析 内存管理/内存优化技巧
查看>>
hiho1079 线段树区间改动离散化
查看>>
【BZOJ 5222】[Lydsy2017省队十连测]怪题
查看>>
第二次作业
查看>>
【input】 失去焦点时 显示默认值 focus blur ★★★★★
查看>>
Java跟Javac,package与import
查看>>
day-12 python实现简单线性回归和多元线性回归算法
查看>>
Json格式的字符串转换为正常显示的日期格式
查看>>
[转]使用 Razor 进行递归操作
查看>>
[转]Android xxx is not translated in yyy, zzz 的解决方法
查看>>
docker入门
查看>>
Android系统--输入系统(十一)Reader线程_简单处理
查看>>