Find Median

Problem Statement

The median of a finite list of numbers can be found by arranging all the integers from lowest to highest value and picking the middle one. For example, the median of  {3,3,5,9,11}  is  5 . If there is an even number of integers, then there is no single middle value, and the median is then usually defined to be the mean of the two middle values. For examples, the median of  {3,5,7,9}  is  (5+7)2=6 .

Given that integers are read from a data stream, find the median of elements read so far in an efficient way.

Input Format

The first line of input will contain integer  N , i.e. the number of integers in the data stream.
The next  N  lines will contain an integer  ai  each in order.

Constraints 
1N105  
0ai105

Output Format

Print  N  integers, i.e. the median after each of the input. Report it with precision up to  101 .

Sample Input

10
1
2
3
4
5
6
7
8
9
10

Sample Output

1.0
1.5
2.0
2.5
3.0
3.5
4.0
4.5
5.0
5.5

Explanation

See the sorted list after each input.

解题思路:用一个最大堆维护序列中位于前半段位置处的数,采用一个最小堆维护序列中后半段位置处的数,不断更新这两个堆,然后在O(logn)的时间内求解出当前的中位数,总的时间复杂度为O(logn).

代码1:

#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <vector>
#include <queue>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 100010;

priority_queue<int, vector<int>, less<int> > pq1;
priority_queue<int, vector<int>, greater<int> > pq2;

void init() {
    while(!pq1.empty()) pq1.pop();
    while(!pq2.empty()) pq2.pop();
}

int get(int x) {
    if(x % 2 == 0) return x / 2 + 1;
    return (x + 1) / 2;
}

int main() {

    int n, x;
    init();
    scanf("%d", &n);
    for(int i = 1; i <= n; ++i) {
        scanf("%d", &x);
        if((int)pq1.size() < get(i)) {
            pq2.push(x);
            int t = pq2.top();
            pq2.pop();
            pq1.push(t);
        } else {
            if(pq1.top() > x) {
                pq1.push(x);
                int t = pq1.top();
                pq1.pop();
                pq2.push(t);
            } else {
                pq2.push(x);
            }
        }
        if(i % 2) {
            printf("%.1lf\n", pq1.top() * 1.0);
        } else {
            int t = pq1.top();
            pq1.pop();
            printf("%.1lf\n", (t + pq1.top())/2.0);
            pq1.push(t);
        }
    }
    return 0;
}

代码2:

#include <cstdio>
#include <vector>
#include <queue>
#include <functional>
using namespace std;

int main() {
    priority_queue<int, vector<int>, greater<int> > minQ;
    priority_queue<int> maxQ;
    int N, a;
    
    scanf("%d", &N);
    while (N--) {
        scanf("%d", &a);
        maxQ.push(a);
        if (maxQ.size() > minQ.size() + 1)
            minQ.push(maxQ.top()), maxQ.pop();
        else if (!minQ.empty() && maxQ.top() > minQ.top()) {
            maxQ.push(minQ.top()), minQ.pop();
            minQ.push(maxQ.top()), maxQ.pop();
        }
        
        if (maxQ.size() > minQ.size()) 
            printf("%d.0\n", maxQ.top());
        else {
            a = maxQ.top() + minQ.top();
            printf("%d.%d\n", a / 2, (a & 1) ? 5 : 0);
        }
    }
    
    return 0;
}


### 回答1: 一个 Go 程序,用来查找两个有序数组的中位数,可能如下:func FindMedian(arr1, arr2 []int) float64 { n1 := len(arr1) n2 := len(arr2) if n1 == 0 { return float64(arr2[n2/2]) } if n2 == 0 { return float64(arr1[n1/2]) } if n1 == 1 && n2 == 1 { return float64(arr1[0] + arr2[0]) / 2.0 } if n1 == 1 { if n2 % 2 == 0 { return float64(arr2[n2/2 - 1] + arr2[n2/2]) / 2.0 } else { return float64(arr2[n2/2]) } } if n2 == 1 { if n1 % 2 == 0 { return float64(arr1[n1/2 - 1] + arr1[n1/2]) / 2.0 } else { return float64(arr1[n1/2]) } } i := n1 - 1 j := n2 - 1 var median1, median2 int for i >= 0 && j >= 0 { if arr1[i] > arr2[j] { median1 = arr1[i] i-- } else { median1 = arr2[j] j-- } } if i == -1 { median2 = arr2[j-1] } else { median2 = arr1[i-1] } return float64(median1 + median2) / 2.0 } ### 回答2: 生成一个Go程序来查找两个有序数组的中位数。 首先,我们需要明确中位数的定义。对于一个有序数组,中位数是指位于数组中间位置的元素。如果数组长度为奇数,中位数就是唯一那个中间元素;如果数组长度为偶数,中位数是中间的两个元素的平均值。 接下来,我们可以使用以下步骤生成一个Go程序来找到两个有序数组的中位数: 1. 声明一个函数,例如findMedian,该函数接受两个有序数组作为输入参数。 2. 初始化变量n,用于存储两个有序数组的总长度。 3. 通过将两个有序数组合并为一个新的有序数组,找到中位数所在的位置。可以使用合并排序或使用两个指针的方法来实现这一步骤。 4. 根据总长度n的奇偶性,分别处理中位数的情况: - 如果n为奇数,返回新数组中间位置的元素作为中位数。 - 如果n为偶数,返回新数组中间两个元素的平均值作为中位数。 5. 在主函数中调用findMedian函数,传递两个有序数组作为参数,并打印出中位数结果。 下面是一个示例的Go程序,通过使用合并排序的方法找到两个有序数组的中位数: ```go package main import "fmt" func merge(nums1 []int, nums2 []int) []int { merged := make([]int, len(nums1)+len(nums2)) i, j, k := 0, 0, 0 for i < len(nums1) && j < len(nums2) { if nums1[i] < nums2[j] { merged[k] = nums1[i] i++ } else { merged[k] = nums2[j] j++ } k++ } for i < len(nums1) { merged[k] = nums1[i] i++ k++ } for j < len(nums2) { merged[k] = nums2[j] j++ k++ } return merged } func findMedian(nums1 []int, nums2 []int) float64 { merged := merge(nums1, nums2) n := len(merged) if n%2 == 0 { return float64(merged[n/2-1]+merged[n/2]) / 2.0 } else { return float64(merged[n/2]) } } func main() { nums1 := []int{1, 3} nums2 := []int{2} median := findMedian(nums1, nums2) fmt.Printf("Median is: %.2f", median) } ``` 以上示例展示了如何使用合并排序的方法找到两个有序数组的中位数。你可以根据自己的需求进行扩展和修改,以适应其他情况和更复杂的需求。 ### 回答3: 下面是一个生成 Go 程序以找到两个有序数组的中位数的示例: ```go package main import ( "fmt" ) func findMedianSortedArrays(nums1 []int, nums2 []int) float64 { m, n := len(nums1), len(nums2) if m > n { nums1, nums2, m, n = nums2, nums1, n, m } imin, imax, half_len := 0, m, (m+n+1)/2 var max_of_left, min_of_right int for imin <= imax { i := (imin + imax) / 2 j := half_len - i if i < m && nums2[j-1] > nums1[i] { imin = i + 1 } else if i > 0 && nums1[i-1] > nums2[j] { imax = i - 1 } else { if i == 0 { max_of_left = nums2[j-1] } else if j == 0 { max_of_left = nums1[i-1] } else { max_of_left = max(nums1[i-1], nums2[j-1]) } break } } if (m+n)%2 == 1 { return float64(max_of_left) } if i == m { min_of_right = nums2[j] } else if j == n { min_of_right = nums1[i] } else { min_of_right = min(nums1[i], nums2[j]) } return float64(max_of_left+min_of_right) / 2.0 } func max(a, b int) int { if a > b { return a } return b } func min(a, b int) int { if a < b { return a } return b } func main() { nums1 := []int{1, 3} nums2 := []int{2} median := findMedianSortedArrays(nums1, nums2) fmt.Printf("The median is: %.2f\n", median) } ``` 这个程序实现了在合并后的有序数组中找到中位数的逻辑。它首先判断数组的大小,然后使用二分查找的方法从较小的数组开始分割,保证左边的元素数量等于右边(或比右边多1)。然后通过比较左侧的最大值和右侧的最小值来确定中位数。如果数组长度是奇数,则直接返回中位数的值;如果是偶数,则计算左侧最大值和右侧最小值的平均值作为中位数的值。 在 main 函数中,我们定义了两个示例的有序数组 `nums1` 和 `nums2`,然后调用 `findMedianSortedArrays` 函数计算它们的中位数,并打印结果。 请注意,这只是一个示例程序,您可以根据自己的需求进行修改和扩展。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值