首页 > 试题广场 >

1029. Median (25)

[编程题]1029. Median (25)
  • 热度指数:3948 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 64M,其他语言128M
  • 算法知识视频讲解
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.

输入描述:
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 (<=1000000) 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.


输出描述:
For each test case you should output the median of the two given sequences in a line.
示例1

输入

4 11 12 13 14
5 9 10 15 16 17

输出

13
//pat的内存限制是1.5MB,开两个数组会爆掉,那就开一个吧。
//#include "stdafx.h"
#include <cstdio>
const int Max = 1000001;
int a[Max];
int main(){
    int n, m;
    scanf("%d", &n);
    for(int k = 0; k < n; ++k)
        scanf("%d", &a[k]);
    scanf("%d", &m);
    a[n] = (1<<31) -1;
    int mid = (n+m -1)/2;
     int cnt = 0, i = 0, j= 0, b = 0;
    if(m > 0){scanf("%d", &b);}
    while(cnt < mid){
        if(j >= m) b = (1<<31) -1;
        if(a[i] < b)i++;
        else {scanf("%d", &b);j++;}
        cnt++;
    }
    printf("%d\n", ((a[i]<b)? a[i]:b));
    return 0;
}

发表于 2018-07-31 13:18:42 回复(1)

时间复杂度O(log(min(m,n))); m,n分别是两个数组的长度
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
	vector<vector<int> > arrays(2);
	int totalAmount = 0;
	for (int i = 0; i < 2; i++)
	{
		int amount;
		cin >> amount;
		totalAmount += amount;
		arrays[i].resize(amount, 0);
		for (int j = 0; j < amount; j++)
		{
			cin >> arrays[i][j];
		}
	}

	int position = (totalAmount-1) / 2;
	vector<int> &n1 = arrays[0], &n2 = arrays[1];
	if(n1.size()>n2.size())
	{
		n1.swap(n2);
	}
	
	int l = 0, r = n1.size() - 1;
	while(l<=r)
	{
		int p1 = l + ((r - l) >> 1);
		int p2 = position - p1;
		if(n1[p1]>=n2[p2])
		{
			r = p1 - 1;
		}else
		{
			l = p1 + 1;
		}
	}

	cout << max(l > 0 ? n1[r] : INT32_MIN, position - l < n2.size() ? n2[position - l] : INT32_MIN);

	return 0;
}

编辑于 2016-08-29 09:46:56 回复(0)
暴力解决,刚开始提交发现有段错误,后来发现是牛客题目里 N 的范围和 PTA 的不一样,改一下数组大小就行
#include<iostream>
#include<algorithm>
using namespace std;
int n, m, a[2000010];
int main() {
	cin >> n;
	for (int i = 0; i < n; i++) cin >> a[i];
	cin >> m;
	for (int i = n; i < m + n; i++) cin >> a[i];
	sort(a, a + n + m);
	cout << a[(n + m - 1) / 2];
}


发表于 2022-05-19 14:29:25 回复(0)
pat的数据比较“暴力”,而且只提供了1.5M内存,因为题目说了最大数值不超过long,即使只开一个数组也有三个测试点超内存。
所以可以分别用两个数组(一个int,一个long),因为序列都是递增,直接把小于MAX_INT的值存到int数组,其他存到long数组,访问整个数组的时候注意一下就可以了
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <math.h>

using namespace std;
const int maxn = 200001;  //牛客网这里要改成1000000
const int MAX_INT = 0x7fffffff;
int sequence1[maxn];
long sequence2[maxn];
int main() {
    int n1;
    scanf("%d", &n1);
    int seq1_len=0, seq2_len=0, index1=0, index2=0;
    for(int i=0; i<n1; i++) {
        long num;
        scanf("%ld",&num);
        if(num<MAX_INT){
            sequence1[index1] = (int)num;
            seq1_len++;
            index1++;
        }else{
            sequence2[index2] = num;
            seq2_len++;
            index2++;
        }
    }

    int n2;
    scanf("%d", &n2);
    int mid_pos = (n1+n2)%2==0? (n1+n2)/2-1 : (n1+n2)/2;
    int cur_pos = 0, j=0, i=0;
    index1=0, index2=0;
    long seq_num;
    bool flag = true;
    while(j<n2&&i<n1) {
        long num, first_seq_num;
        if(index1<seq1_len)
            first_seq_num = sequence1[index1];
        else
            first_seq_num = sequence2[index2];
        if(flag)
            scanf("%ld",&seq_num);

        if(first_seq_num >= seq_num) {
            num = seq_num;
            j++;
            flag = true;
        } else {
            num = first_seq_num;
            i++;
            if(index1 >= seq1_len)
                index2++;
            index1++;
            flag = false;
        }
        if(cur_pos == mid_pos) {
            printf("%ld\n",num);
            cur_pos++;
            break;
        }
        cur_pos++;
    }

    if(cur_pos <= mid_pos) {
        if(i == n1) {
            long temp = seq_num;
            while(cur_pos<mid_pos){
                scanf("%ld", &temp);
                cur_pos++;
            }
            printf("%ld\n",temp);
        } else {
            if(i+mid_pos-cur_pos<seq1_len){
                printf("%d\n",sequence1[i+mid_pos-cur_pos]);
            }else{
                printf("%ld\n",sequence2[index2+mid_pos-cur_pos]);
            }
            //printf("%ld\n",sequence1[i+mid_pos-cur_pos]);
        }
    }
}



发表于 2019-08-29 17:19:28 回复(0)
import java.util.*;

public class Main{
    public static void main(String[] args){
        Scanner sc=new Scanner(System.in);
        int n=sc.nextInt();
        int[] a=new int[n];
        for(int i=0;i<n;i++)
            a[i]=sc.nextInt();
        int m=sc.nextInt();
        int[] b=new int[m];
        for(int i=0;i<m;i++)
            b[i]=sc.nextInt();
        int[] result=new int[m+n];
        int aIndex=0,bIndex=0;
        for(int i=0;i<m+n;i++){
            if(aIndex<n && bIndex<m){
                if(a[aIndex]<b[bIndex]){
                    result[i]=a[aIndex++];
                }else{
                    result[i]=b[bIndex++];
                }
            }else{
                break;
            }
        }
        if(aIndex==n && bIndex!=m){
            for(int i=bIndex;i<m;i++){
                result[n+i]=b[i];
            }
        }else if(aIndex!=n && bIndex==m){
            for(int i=aIndex;i<n;i++){
                result[m+i]=a[i];
            }
        }
        System.out.println(result[(m+n-1)/2]);
    }
}

发表于 2018-10-06 21:41:53 回复(0)
这道题有点让人怀疑人生
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
	int length, num;
	while (cin >> length)
	{
		vector<int> data;
		for (int i = 0; i < length; i++)
		{
			cin >> num;
			data.push_back(num);
		}
		cin >> length;
		for (int i = 0; i < length; i++)
		{
			cin >> num;
			data.push_back(num);
		}
		sort(data.begin(), data.end());
		cout << data[(data.size() - 1) / 2] << endl;
	}
	return 0;
}

发表于 2017-04-28 16:53:37 回复(0)
__author__ = 'Yaicky'

while True:
    try:
        numList1 = map(int, raw_input().strip().split())
        numList1.remove(numList1[0])
        numList2 = map(int, raw_input().strip().split())
        numList2.remove(numList2[0])

        numList1.extend(numList2)
        numList1.sort()

        if len(numList1)%2:
            pos = len(numList1) / 2
        else:
            pos = len(numList1) / 2 - 1
        print numList1[pos]
    except:
        break


#内存超限  爆炸....

发表于 2016-06-23 14:55:03 回复(0)
import java.util.Scanner;
//最后一个测试用例有毒,用collections.sort排序都超时,我们能写出更优的排序方法吗?
//显然不可能。于是只能换个思路,因为只要求中位数,所以直接比较就行了,不用排序(类似二路合并排序)
public class Main {

	public static void main(String[] args) {
		Scanner in=new Scanner(System.in);
		int m=in.nextInt();
		int a[]=new int[m];
		for(int i=0;i<m;i++){
			a[i]=in.nextInt();
		}
		int n=in.nextInt();
		int b[]=new int[n];
		for(int i=0;i<n;i++){
			b[i]=in.nextInt();
		}

		int loc=(m+n+1)/2;
		int count=0;
		int i=0;
		int j=0;
		int median=0;
		while(count<loc){
			if(a[i]<b[j]){
				median=a[i++];
			}else median=b[j++];
			count++;
		}
		System.out.println(median);
	}
}


编辑于 2016-10-30 10:45:28 回复(1)
两种思路,一个正常归并排序-like的算法,另一个直接暴力合并、排序。
#include<iostream>
#include<string>
#include<map>
#include<vector>
#include<algorithm>
#include<climits>

#define INF 2147483647
#define MIN INF+1
#define ll long long

using namespace std;

void work1() {
    int N, M;
    cin >> N;
    ll a[N];
    for (int i = 0; i < N; ++i)
        cin >> a[i];
    cin >> M;
    ll b[M];
    for (int j = 0; j < M; ++j)
        cin >> b[j];

    int pa = 0, pb = 0, pc = 0;
    ll last_num = 666;
    while(pc <= (N + M - 1) / 2) {
        ll left = LONG_LONG_MAX, right = LONG_LONG_MAX;
        if(pa < N)
            left = a[pa];
        if(pb < M)
            right = b[pb];
        last_num = left < right ? a[pa++] : b[pb++];
        pc++;
    }
    cout << last_num << endl;
}

void work2() {
    int N, M;
    cin >> N;
    vector<int> v;
    for (int i = 0; i < N; ++i) {
        int tmp;
        cin >> tmp;
        v.push_back(tmp);
    }
    cin >> M;
    for (int i = 0; i < M; ++i) {
        int tmp;
        cin >> tmp;
        v.push_back(tmp);
    }
    sort(v.begin(), v.end());
    cout << v[(M+N-1)/2] << endl;
}

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(0);

    work1();
    // work2();

    return 0;
}


发表于 2020-09-19 19:01:12 回复(0)
a = list(map(int,input().split()))
b = list(map(int,input().split()))
c = sorted(a[1:] + b[1:])
print(c[(a[0] + b[0] - 1) // 2])
原代码pta上最后一个用例极难通过(10次碰上一次不超时)
a = list(map(int,input().split()))
b = list(map(int,input().split()))

if a[(a[0] + 1) // 2] > b[(b[0] + 1) // 2]:
    a,b = b,a
if a[-1] > b[1]:
    c = sorted(a[(a[0] + 1) // 2:] + b[1:(b[0] + 1) // 2 + 1])
    print(c[(a[0] + b[0] + 1) // 2 - (a[0] + 1) // 2])
else:
    if a[0] >= b[0]:
        print(a[(a[0] + b[0] + 1) // 2])
    else:
        print(b[(a[0] + b[0] + 1) // 2 - a[0]])
改了之后提交10次碰上1次超时



编辑于 2020-02-07 13:41:07 回复(0)
针对Java,本题要求的测试数据有long,但是用long会有一个测试用例超时,改成int就不回超时了。
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner scanner=new Scanner(System.in);
        int l1=scanner.nextInt();
        int[]S1=new int[l1];
        for(int i=0;i<l1;i++){
            S1[i]=scanner.nextInt();
        }

        int l2=scanner.nextInt();
        int[]S2=new int[l2];
        for(int i=0;i<l2;i++){
            S2[i]=scanner.nextInt();
        }

        int target=(l1+l2+1)/2;

        int cnt=0;
        for(int i=0,j=0;i<l1&&j<l2;){
            int s1=S1[i];
            int s2=S2[j];

            cnt++;

            if(s1<s2){
                if(cnt==target){
                    System.out.print(s1);
                    break;
                }
                i++;
            }else{
                if(cnt==target){
                    System.out.print(s2);
                    break;
                }
                j++;
            }
        }
    }
}

发表于 2019-05-05 15:30:01 回复(0)
//1008.Median
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
    vector<long long> v;
    int n,t; cin>>n;
    for(int i=0;i<n;i++){
        cin>>t; v.push_back(t);
    }
    cin>>n;
    for(int i=0;i<n;i++){
        cin>>t; v.push_back(t);
    }
    sort(v.begin(), v.end()); //默认升序
    //cout<<v[v.size()%2==0?v.size()/2-1:v.size()/2];
    cout<<v[(v.size()-1)/2];
    return 0;
}
发表于 2019-02-27 09:22:22 回复(0)
排序的时间复杂度的下限是Nlog(N),那我就用堆吧
import heapq
nums=[]
nums.extend(map(int,raw_input().split())[1:])
nums.extend(map(int,raw_input().split())[1:])
print heapq.nsmallest((len(nums)+1)/2,nums)[-1]
发表于 2019-01-16 14:15:03 回复(0)
a = list(map(int,input().split()))
b = list(map(int,input().split()))
lst = a[1:]+b[1:]
lst.sort()
if len(lst)%2!=0:
    print(lst[len(lst)//2])
else:
    print(lst[len(lst)//2-1])

发表于 2018-11-27 18:58:03 回复(0)
这道题简直爆炸,PAT内存限制1.5M,我看了一下目前java还没人写出来达到要求的,果断转行c++
发表于 2018-10-11 20:41:43 回复(0)
思路:常规使用sort输出
#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
using namespace  std;

int main()
{
    //ifstream cin("test.txt");
    int n1, n2;
    while (cin >> n1)
    {
        vector<int> v1(n1);
        for (int i = 0; i < n1; i++)
        {
            cin >> v1[i];
        }
        cin >> n2;
        int temp;
        for (int i = 0; i < n2; i++)
        {
            cin >> temp;
            v1.push_back(temp);
        }
        sort(v1.begin(), v1.end());
        cout << v1[v1.size() % 2 == 0 ? v1.size() / 2 - 1 : v1.size() / 2] << endl;
    }
    system("pause");
}

发表于 2018-08-16 20:28:05 回复(1)
// 输入序列是有序的,如果重新排序将会花费大量时间开销
#include <iostream>
#include <vector>
#include <fstream>
using namespace std;

int main()
{
    ifstream cin("case.txt");

    // 输入序列S1
    int m1 = 0;
    cin >> m1;
    vector<long int>va;
    long int x = 0;
    for (int i = 0;i < m1;++i)
    {
        cin >> x;
        va.push_back(x);
    }
    ///////////////////////////

    // 输入序列S2
    int m2 = 0;
    cin >> m2;
    vector<long int>vb;
    for (int i = 0;i < m2;++i)
    {
        cin >> x;
        vb.push_back(x);
    }
    ///////////////////////////

    int loop = 0, i = 0;
    bool flag = false;
    if ((m1 + m2) % 2 == 0)
    {
        loop = (m1 + m2) / 2;
    }
    else
    {
        loop = (m1 + m2 - 1) / 2;
    }
    while (!va.empty() && !va.empty())
    {
        if (va.back() > vb.back())
        {
            va.pop_back();
        }
        else
        {
            vb.pop_back();
        }
        i++;
        if (i == loop)
        {
            flag = true;
            break;
        }
    }

    if (flag == true)
    {
        int out = (va.back() > vb.back()) ? (va.back()) : (vb.back());
        cout << out << endl;
    }
    else
    {
        if (va.empty())
        {
            if ((m1 + m2) % 2 == 0) // even
            {
                cout << vb[loop - 1] << endl;
            }
            else // odd
            {
                cout << vb[loop] << endl;
            }
        }
        else
        {
            if ((m1 + m2) % 2 == 0) // even
            {
                cout << va[loop - 1] << endl;
            }
            else // odd
            {
                cout << va[loop] << endl;
            }
        }
    }
    getchar();
    return 0;
}

发表于 2017-11-23 21:26:42 回复(0)
#include <sstream>
#include <iostream>
#include <algorithm>
using namespace std;

const int maxn = 1000000 + 10;

long a1[maxn * 2];
long a2[maxn];

bool read_list(long* a){
	string line;
	while(!getline(cin, line)) return false;
	stringstream ss(line);
	int x;
	int n = 0;
	while(ss >> x) a[n++] = x;
	return (n > 0);
}

int main(){
	if(read_list(a1))
		read_list(a2);
	for(int i=1;i<=a2[0];i++){
		a1[a1[0]+i] = a2[i];
	}
	sort(a1+1, a1+a1[0]+a2[0]+1);
	int n_sum = a1[0] + a2[0];
	int pos = (n_sum % 2 == 1)?(n_sum / 2 + 1):(n_sum / 2);
	cout << a1[pos] << endl;
	return 0;
}

发表于 2017-07-27 20:22:26 回复(0)
//类似归并,但是还有会有部分例子超时
import java.util.Scanner;

public class Main {
	
	public static void main(String[] args){
		Scanner in = new Scanner(System.in);
		int N = in.nextInt();
		int[] arr1 = new int[N];
		for(int i=0;i<N;i++){
			arr1[i] = in.nextInt();
		}
		int M = in.nextInt();
		int[] arr2 = new int[M]; 
		for(int i=0;i<M;i++){
			arr2[i] = in.nextInt();
		}
		
		int[] arr = new int[M+N];
		int len = arr.length/2 + arr.length%2;
		int i=0;
		int j=0;
		for(int k=0;k<len;k++){
			if(arr1[i]<arr2[j]){
				arr[k]=arr1[i];
				i++;
			}else{
				arr[k]=arr2[j];
				j++;
			}
		}
		System.out.println(arr[len-1]);

	}
}

发表于 2017-06-28 14:16:44 回复(0)
//1008  Median(25)
#include<iostream>
#include<vector>
#include<cmath>
using namespace std;
intmain()
{
    intM, N;
    longinttemp;
    vector<longint> arr1, arr2,result;
    //cout << "输入两行有序数组,第一个数是数组个数:" << endl;
    cin >> M;
    for(inti = 0; i < M; i++)
    {
        cin >> temp;
        arr1.push_back(temp);
    }
    cin >> N;
    for(inti = 0; i < N; i++)
    {
        cin >> temp;
        arr2.push_back(temp);
    }
     
 
    intmid =(M + N + 1) / 2;
     
    if(arr1[M-1] < arr2[0])
    {
        arr1.insert(arr1.end(),arr2.begin(),arr2.end());
        cout << arr1[mid-1] << endl;
    }
    elseif(arr2[M-1] < arr1[0])
    {
        arr2.insert(arr2.end(), arr1.begin(), arr1.end());
        cout << arr2[mid -1] << endl;
    }
    else
    {
        inti = 0;
        intj = 0;
        while(result.size()<=mid)
        {
            if(i == M)
            {
                result.push_back(arr2[j]);
                j++;
            }
            elseif(j == N)
            {
                result.push_back(arr1[i]);
                i++;
            }elseif(arr1[i] <= arr2[j])
                {
                    result.push_back(arr1[i]);
                    i++;
                }  
                else
                {
                    result.push_back(arr2[j]);
                    j++;
                }
         
        }
             
        cout << result[mid-1] << endl;
    }
 
     
 
    //system("pause");
    return0;
}


前面的测试用例都正确,最后两个测试用例报错说段错误,求大神看看哪里错了?
发表于 2016-08-31 16:44:47 回复(0)