分治法解决i 中位数问题

问题描述

设X[ 0 : n - 1]和Y[ 0 : n – 1 ]为两个数组,每个数组中含有n个已排好序的数。找出X和Y的2n个数的中位数。

编程任务

利用分治策略试设计一个O (log n)时间的算法求出这2n个数的中位数。

数据输入

文件的第1行中有1个正整数n(n<=200),表示每个数组有n个数。接下来的两行分别是X,Y数组的元素。

结果输出

程序运行结束时,输出计算出的中位数。

输入示例

3

5 15 18

3 14 21

输出示例

14.5

方法一:归并排序

#include<iostream>
#include<vector>
#include<cmath>
#include <algorithm> 
using namespace std;


//归并排序
void merge(vector<int>&c, int low,int mid, int hight)
{
    vector<int>temp(hight - low + 1);
    int i = low, j = mid + 1, k = 0;
    while (i <= mid && j <= hight)
    {
        if (c[i] <= c[j])
        {
            temp[k++] = c[i++];
        }
        else 
        {
            temp[k++] = c[j++];
        }
    }
    while (i <= mid)
    {
        temp[k++] = c[i++];
    }
    while (j <= hight)
    {
        temp[k++] = c[j++];
    }
    k = 0;
    for (int i = low; i <= hight; i++)
    {
        c[i] = temp[k++];
    }
    temp.clear();
}

void mergesort(vector<int>&c, int low, int hight)
{
    if (low < hight)
    {
        int mid = (low + hight) / 2;
        mergesort(c, low, mid);          
        mergesort(c, mid + 1, hight);    
        merge(c, low, mid, hight);       //进行合并操作
    }
}

int main() 
{
    int n;
    cin >> n;
    vector<int> a(n);
    vector<int> b(n);
    vector<int> c(2*n);
    for (int i = 0; i < n; i++) {
        cin >> a[i];
        c[i] = a[i];
    }
    for (int i = 0; i < n; i++) {
        cin >> b[i];
        c[i + n] = b[i];
    }
  
    mergesort(c, 0, 2*n - 1);

    cout << (c[n-1] + c[n ]) / 2.0;
        
    return 0;
}

方法二:直接判断是否会存在中位数在一个数组中

3

1 2 3

-1 4 5    情况

#include<iostream>
#include<vector>
#include<cmath>
#include<algorithm> 
using namespace std;

// 计算中位数
double zhong(vector<int> a) 
{
    int len = a.size();
    if (len % 2 == 0) {
        return (a[len / 2 - 1] + a[len / 2]) / 2.0;
    }
    else {
        return a[len / 2];
    }
}

// 递归计算中位数
double zhongwei(vector<int> a, vector<int> b, int n)
{
    if (n == 1) 
    {
        return (a[0] + b[0]) / 2.0;
    }

    //防止中位数在一个数组中
    if (n % 2 == 0)
    {
        if (a[n / 2 - 1] > b[n / 2 - 1] && a[n / 2] < b[n / 2 ])
        {
            return  (a[n / 2 - 1] + a[n / 2]) / 2.0;
        }
    }
    if (n % 2 == 0)
    {
        if (b[n / 2 - 1] > a[n / 2 - 1] && b[n / 2] < a[n / 2 ])
        {
            return  (b[n / 2 - 1] + b[n / 2]) / 2.0;
        }
    }

    //防止逆序
    if (a[1] < a[0])
    {
        reverse(a.begin(), a.end());
    }
    if (b[1] < b[0])
    {
        reverse(b.begin(), b.end());
    }
    
    double x = zhong(a);
    double y = zhong(b);
    double f = 0;
    if (x == y) 
    {
        return x;
    }
    if (x > y) {
        vector<int> c(a.begin(), a.begin() + (int)ceil((float)n / 2));
        vector<int> d(b.begin() + n / 2, b.end()); // 修正切片范围
        n = (int)ceil((float)n / 2);
        f = zhongwei(c, d, n);
    }
    if (x < y) {
        vector<int> c(a.begin() + n / 2, a.end()); // 修正切片范围
        vector<int> d(b.begin(), b.begin() + (int)ceil((float)n / 2));
        n = (int)ceil((float)n / 2);
        f = zhongwei(c, d, n);
    }
    return f;
}


int main() {
    int n;
    cin >> n;
    vector<int> a(n);
    vector<int> b(n);
   
    for (int i = 0; i < n; i++) 
    {
        cin >> a[i];
    }
    for (int i = 0; i < n; i++) 
    {
        cin >> b[i];
    }
   
    cout << zhongwei(a, b, n);
    return 0;
}

  • 27
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值