博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【算法刷题】-中位数(数组、数据流)
阅读量:3924 次
发布时间:2019-05-23

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

微信搜索:编程笔记本。获取更多干货!

微信搜索:编程笔记本。获取更多干货!

点击上方蓝字关注我,我们一起学编程

欢迎小伙伴们分享、转载、私信、赞赏

中位数

文章目录

中位数是有序数据中间位置的数。当数据总数为奇数时,中位数就是中间位置的一个数;当数据总数为偶数时,中位数就是中间两个相邻位置的平均值。

1 寻找两个有序数组的中位数

微信搜索:编程笔记本。获取更多干货!

微信搜索:编程笔记本。获取更多干货!

题目描述:

给定两个递增排序的数组,长度分别为 m 和 n ,要求找出这两个数组的中位数。

1.1 合并数据法

由于这两组数据不在同一个集合内,因此给我们寻找中位数带来了一定的困难。一个最直观的想法就是,将数据合并到同一个数据集中,然后直接找出中间位置的数据即可。下面是参考代码:

时间复杂度:O(m+n)

空间复杂度:O(m+n)

class Solution {
public: double findMedianSortedArrays(vector
& nums1, vector
& nums2) {
double ans; int idx1 = 0; /* 数组1的元素的游标 */ int idx2 = 0; /* 数组2的元素的游标 */ vector
nums; /* 合并的数据集 */ while (idx1 < nums1.size() && idx2 < nums2.size()) {
if (nums1[idx1] < nums2[idx2]) {
nums.push_back(nums1[idx1++]); } else {
nums.push_back(nums2[idx2++]); } } while (idx1 < nums1.size()) {
nums.push_back(nums1[idx1++]); } while (idx2 < nums2.size()) {
nums.push_back(nums2[idx2++]); } if (nums.size() % 2 == 0) {
int idx = nums.size() / 2; ans = (nums[idx - 1] + nums[idx]) / 2.0; } else {
int idx = nums.size() / 2; ans = nums[idx]; } return ans; }};

1.2 二分查找法

上面的解法显然不是最优的解法,因为我们没有使用到“数组有序”这个条件。我们有一个直觉,这两个数组本来就是有序的,那么我们可不可以在 log 时间内求解问题呢?于是,我们想到了二分查找:在两个数组中寻找出较小的若干个数据,即可找到中间位置的数据。

时间复杂度:O(log(m+n))

空间复杂度:O(1)

微信搜索:编程笔记本。获取更多干货!

微信搜索:编程笔记本。获取更多干货!

class Solution {
public: double findMedianSortedArrays(vector
& nums1, vector
& nums2) {
double ans; int totalLength = nums1.size() + nums2.size(); if (totalLength % 2 == 1) {
ans = getKthElement(nums1, nums2, (totalLength + 1) / 2); } else {
ans = (getKthElement(nums1, nums2, totalLength / 2) + getKthElement(nums1, nums2, totalLength / 2 + 1)) / 2.0; } return ans; } int getKthElement(const vector
& nums1, const vector
& nums2, int k) {
int ans; int m = nums1.size(); int n = nums2.size(); int index1 = 0; int index2 = 0; while (true) {
/* 边界情况 */ if (index1 == m) {
/* 中位数在数组2中 */ return nums2[index2 + k - 1]; } if (index2 == n) {
/* 中位数在数组1中 */ return nums1[index1 + k - 1]; } if (k == 1) {
ans = min(nums1[index1], nums2[index2]); break; } /* 正常情况 */ int newIndex1 = min(index1 + k / 2 - 1, m - 1); int newIndex2 = min(index2 + k / 2 - 1, n - 1); int pivot1 = nums1[newIndex1]; int pivot2 = nums2[newIndex2]; if (pivot1 <= pivot2) {
k -= newIndex1 - index1 + 1; index1 = newIndex1 + 1; } else {
k -= newIndex2 - index2 + 1; index2 = newIndex2 + 1; } } return ans; }};

微信搜索:编程笔记本。获取更多干货!

微信搜索:编程笔记本。获取更多干货!

2. 寻找数据流中的中位数

由于数据流中的数据总量不能确定,所以我们只能将已从数据流中获取的数据存入某种数据结构中,然后在取中位数时从数据结构中取。在这里,我们使用这种数据结构。

class MedianFinder {
/***/public: double findMedian() {
if ((min.size() + max.size()) % 2 == 0) {
return (min[0] + max[0]) / 2.0; } else {
return min[0]; } } void addNum(int num) {
// 总数据数为偶数时将num插入到小根堆 if ((min.size() + max.size()) % 2 == 0) {
if (max.size() > 0 && num < max[0]) {
max.push_back(num); push_heap(max.begin(), max.end(), less
()); num = max[0]; pop_heap(max.begin(), max.end(), less
()); max.pop_back(); } min.push_back(num); push_heap(min.begin(), min.end(), greater
()); } else {
// 总数据数为奇数时将num插入到大根堆 if (min.size() > 0 && num > min[0]) {
min.push_back(num); push_heap(min.begin(), min.end(), greater
()); num = min[0]; pop_heap(min.begin(), min.end(), greater
()); min.pop_back(); } max.push_back(num); push_heap(max.begin(), max.end(), less
()); } }private: vector
min; vector
max;};

微信搜索:编程笔记本。获取更多干货!

微信搜索:编程笔记本。获取更多干货!

你可能感兴趣的文章
剑指 Offer 29. 顺时针打印矩阵
查看>>
剑指 Offer 31. 栈的压入、弹出序列
查看>>
剑指 Offer 32 - III. 从上到下打印二叉树 III
查看>>
剑指 Offer 33. 二叉搜索树的后序遍历序列
查看>>
剑指 Offer 68 - I. 二叉搜索树的最近公共祖先
查看>>
剑指 Offer 68 - II. 二叉树的最近公共祖先
查看>>
剑指 Offer 18. 删除链表的节点
查看>>
剑指 Offer 32 - II. 从上到下打印二叉树 II
查看>>
杭电oj-2011 多项式求和 C++
查看>>
杭电oj-2014 青年歌手大奖赛_评委会打分 C++
查看>>
杭电oj-2015 偶数求和 C++
查看>>
杭电oj-2016 数据的交换输出 C++
查看>>
杭电oj-2017 字符串统计 C++
查看>>
杭电oj-2018 母牛的故事 C++
查看>>
Educational Codeforces Round 87 (Rated for Div. 2)----题目+题解(A、B)
查看>>
Codeforces Round #647 (Div. 2) - Thanks, Algo Muse!B. Johnny and His Hobbies(异或)---题解
查看>>
使用WinINet获取网页源代码
查看>>
Ansi、Unicode、UTF-8字符串之间的转换和写入文本文件
查看>>
error C1189:#error:This file requires _WIN32_WINNT to be #defined at least to 0x0403
查看>>
CentOS yum 源的配置与使用
查看>>