PAT 1029 Median

题目描述

Given an increasing sequence S of N integers, the median is the number at the middle position. For example, the median of S1 = { 11, 12, 13, 14 } is 12, and the median of S2 = { 9, 10, 15, 16, 17 } is 15. The median of two sequences is defined to be the median of the nondecreasing sequence which contains all the elements of both sequences. For example, the median of S1 and S2 is 13.

Given two increasing sequences of integers, you are asked to find their median.

Input Specification:

Each input file contains one test case. Each case occupies 2 lines, each gives the information of a sequence. For each sequence, the first positive integer N (≤2×10^5​) is the size of that sequence. Then N integers follow, separated by a space. It is guaranteed that all the integers are in the range of long int.

Output Specification:

For each test case you should output the median of the two given sequences in a line.


题目大意

  给定一个包含N个整数的递增序列S,中位数是指在中间位置的数。例如,S1={11,12,13,14}的中位数是12,S2={9,10,15,16,17}的中位数是15。两个序列的中位数被定义为包含两个序列所有元素的非递减的序列的中位数。例如,S1和S2的中位数是13。
  给两个递增的整数序列,你需要找出他们的中位数。

输入说明

  每一个输入文件包含一个测试用例。每个测试用例占两行,每一行给出一个序列的信息。对于每一个序列,第一个正整数N(<= 2x10^5)是序列的大小。然后跟着N个由空格分隔的整数。保证所整数的范围都能用long int来表示。

输出说明

每一个测试用例你应该将中位数输出到一行中。


题目分析

  定义一个数组S1,将第一个序列的全部数据存储下来。根据两个序列的长度,可以求得将两个序列按非递减合并成一个序列时,中位数的下标。假设两个序列的长度分别为n1n2,中位数的下标为mid = (n1 + n2 + 1) / 2 - 1,至于为什么,大家可以自行推导。
  这个题最直接的思路就是将两个序列合并成一个序列,再求中位数,但是这种方法会导致运行超时。仔细想一下,这道题给的数据量虽然可能很大,但是我们只需要其中的一个数,所以没必要将全部数据进行排序。
  我所采用的方法是,将第一个序列的数据全部存储到数组S1中,读取第二个序列时,不进行存储,而是定义一个索引下标index,比较读入的数据和S1[index]的大小关系,若读入的数据大,则让index自加,直到读入的数据小于等于S1[index]。这里有一个问题就是若读入的数据比第一个序列的所有数都大,这样可能会引起数组越界。解决方法是在第一个序列的最后添加一个最大的整数,即S1[n1] = INT_MAX,这样就不用担心index一直自加导致数组越界了。
  当S1[index]大于等于读入的数据时,假设读入的是第二个序列的第i个数据,那么index+i就是将两个序列按非递减排序后,当前读入的数据所在的位置。比较midindex+i的大小关系,如果相等,那么当前读入的数据就是中位数。如果index+i大于mid,那么说明中位数在序列S1中,并且是在从S1[index]开始向前数的第index+i-mid个位置。所以此种情况的中位数下标为index - (index +i -mid)

#include <bits/stdc++.h>
using namespace std;
int S1[200005];
int main()
{
    ios::sync_with_stdio(false);//提高cin和cout的速度
    int n1, n2,index = 0;//index为第一个序列的索引
    int element;//序列2的元素
    cin >> n1;
    for (int i = 0; i < n1; i++)
        cin >> S1[i];
    S1[n1] = INT_MAX;//防止访问S1时越界
    cin >> n2;
    int mid = (n1 + n2 + 1) / 2 - 1;//假设将S1和S2按非递减排序,mid就是median的索引
    for (int i = 0; i < n2; i++) {
        cin >> element;
        for (; S1[index] < element; index++);
        if (index + i == mid) {
            cout << element;
            return 0;
        }
        else if (index + i > mid) {
            cout << S1[mid - i];
            return 0;
        }
    }
    cout << S1[mid - n2];
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值