首页 > 试题广场 >

在两个长度相等的排序数组中找到上中位数

[编程题]在两个长度相等的排序数组中找到上中位数
  • 热度指数:1201 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/C++ 256M,其他语言512M
  • 算法知识视频讲解
给定两个有序数组arr1和arr2,已知两个数组的长度都为N,求两个数组中所有数的上中位数。
上中位数:假设递增序列长度为n,若n为奇数,则上中位数为第n/2+1个数;否则为第n个数
[要求]
时间复杂度为,额外空间复杂度为

输入描述:
第一行一个整数N,表示数组大小。
接下来一行N个整数,表示arr1内的元素
再接下来一行N个整数,表示arr内的元素


输出描述:
输出一个整数表示答案
示例1

输入

4
1 2 3 4
3 4 5 6

输出

3

说明

总共有8个数,上中位数是第4小的数,所以返回3。
示例2

输入

3
0 1 2
3 4 5

输出

2

说明

总共有6个数,那么上中位数是第3小的数,所以返回2

备注:

记第一个数组是arr1,第二个数组是arr2。先假设两个数组的长度都为偶数,先取到两个数组的中点arr1[mid1]和arr2[mid2]:
  1. 如果他们两个相等,由于arr1[mid1]前面有mid1个数,arr2[mid2]前面也有mid2个数,假设排完序后arr1[mid1]排前面,那肯定有mid1+mid2=n/2个数压在了arr2[mid2]的前面,因此返回arr1[mid1]就行。
  2. 如果不相等,不妨设arr1[mid1]<arr2[mid2],那么上中位数一定不会是它两之中小的那个,也就不可能在arr1中排在arr1[mid1]前面的数之中,同时不可能在arr2中排在arr2[mid2]之后的数之中。于是可以二分去一半的区间中找,从而达成时间复杂度O(logN)的成就。
当两个数组的长度为奇数时,可能性1和长度为偶数时相同。在可能性2中左神手动做了几次中点的比较,考虑中点有没有可能是上中位数再去重复这个过程。但是我觉得思考起来有点晕,这种边界一不小心就搞错了,那我干脆就认为中点是有可能的然后去递归,这样就可以直接套用数组长度为偶数的过程。base case就是当数组长度为1时,返回arr1和arr2中仅剩的那个元素中小的那个就行了。
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;

public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int n = Integer.parseInt(br.readLine().trim());
        String[] strArr = br.readLine().split(" ");
        int[] arr1 = new int[n];
        for(int i = 0; i < n; i++) arr1[i] = Integer.parseInt(strArr[i]);
        strArr = br.readLine().split(" ");
        int[] arr2 = new int[n];
        for(int i = 0; i < n; i++) arr2[i] = Integer.parseInt(strArr[i]);
        System.out.println(getUpMedian(arr1, 0, n - 1, arr2, 0, n - 1));
    }
    
    // 两个数组的考虑范围大小(等长)必须相同
    private static int getUpMedian(int[] arr1, int l1, int r1, int[] arr2, int l2, int r2) {
        if(l1 == r1) return Math.min(arr1[l1], arr2[l2]);
        int mid1 = l1 + ((r1 - l1) >> 1);
        int mid2 = l2 + ((r2 - l2) >> 1);
        if(arr1[mid1] == arr2[mid2]) return arr1[mid1];
        if((r1 - l1 + 1) % 2 == 0){
            // 长度为偶数
            if(arr1[mid1] < arr2[mid2]){
                return getUpMedian(arr1, mid1 + 1, r1, arr2, l2, mid2);
            }else{
                return getUpMedian(arr1, l1, mid1, arr2, mid2 + 1, r2);
            }
        }else{
            // 长度为奇数
            if(arr1[mid1] < arr2[mid2]){
                return getUpMedian(arr1, mid1, r1, arr2, l2, mid2);
            }else{
                return getUpMedian(arr1, l1, mid1, arr2, mid2, r2);
            }
        }
    }
}

发表于 2021-12-01 11:36:58 回复(0)
import java.util.Scanner;
import java.util.Arrays;

public class Main{
    public static void main(String[] args){
        Scanner sc=new Scanner(System.in);
        int n=sc.nextInt();
        int num=2*n;
        int[] arr=new int[num];
        for(int i=0;i<num;i++){
            arr[i]=sc.nextInt();
        }
        Arrays.sort(arr);
        int sum=n/2;
        if(0==sum){
            System.out.print(arr[sum]);
        }else{
            System.out.print(arr[n-1]);
        }
    }
    
}

发表于 2021-03-29 14:06:58 回复(0)