找出两数组的中位数 O(log n ) 分治与递归

设X[0:n - 1 ] 和 Y[0:n - 1 ] 为两个数组,每个数组含有 n 个已经 排好序的数,试设计一个O(log n ) 时间的算法,找出X 和 Y 的 2n个数的中位数
public class Median_of_two_sorted_arrays {//
    public static void main(String args[]){
        //        int []arr1 = {1,4,7,9};
        //        int []arr2 = {2,3,5,6};

        int []arr1 = {1,4,6,8,11};
        int []arr2 = {2,3,5,7,9};

        //        int []arr1 = {1,2,3,4,5};
        //        int []arr2 = {6,7,8,9,10};

        //        int []arr1 = new int[4];
        //        int []arr2 = new int[4];
        //        Scanner scanner = new Scanner(System.in);
        //        for(int i = 0;i < 4;i++){
        //            arr1[i] = scanner.nextInt();
        //        }
        //        for(int i = 0;i < 4;i++){
        //            arr2[i] = scanner.nextInt();
        //        }
        System.out.println("利用分治法求两个有序数组的中位数为:" + findMedianSortedArrays(arr1,arr2));
    }
    public static double findMedianSortedArrays(int []arr1,int []arr2){
        int n = arr1.length;
        int m = arr2.length;
        int L1 = 0,L2 = 0,R1 = 0,R2 = 0,c1,c2,left = 0,right = n - 1;
        c1 = (left + right) / 2;
        while (left <= right){
            c2 = n - c1;
            L1 = (c1 == 0)?arr1[0]:arr1[c1 - 1];//考虑一方数组完全大于另一数组情况
            R1 = (c1 == n - 1)?arr1[n - 1]:arr1[c1];
            L2 = (c2 == 0)?arr2[0]:arr2[c2 - 1];
            R2 = (c2 == n - 1)?arr2[n - 1]:arr2[c2];

            if(c1 == 0){//当arr1完全大于arr2的情况
                return (double)(R2 + L1) /2;
            }
            else if(c1 == n - 1) {//当arr1完全小于arr2的情况
                return (double)(L2 + R1) /2;
            }

            if(L1 > R2){
                c1--;
            }
            else if(L2 > R1){
                c1++;
            }
            else {
                break;
            }
        }
        return ((double)(max(L1,L2)) + min(R1,R2)) / 2;
    }
    public static int max(int a,int b){
        return a > b?a:b;
    }
    public static int min(int a,int b){
        return a < b?a:b;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
解题思路: 首先,中位数的定义是将一组数据按照从小到大(或从大到小)排序后,处于中间位置的那个数。因此,对于这道题,我们需要将个已排好序的数组合并为一个有序数组,然后找出这个有序数组中位数。 最简单的方法是将个数组合并为一个有序数组,然后直接找出中位数。但是,这种方法的时间复杂度是 O(n),不符合题目要求。因此,我们需要采用分治策略来解决这个问题。 具体地,我们可以采用类似于归并排序的方法。将 X 和 Y 分别分成段,分别为 X1, X2 和 Y1, Y2。然后比较 X1 和 Y1 的中位数,设为 m1,比较 X2 和 Y2 的中位数,设为 m2。如果 m1 = m2,则 m1 和 m2 就是整个数组的中位数。如果 m1 < m2,则中位数一定在 X2 和 Y1 中,我们可以继续在 X2 和 Y1 中递归地寻找中位数。如果 m1 > m2,则中位数一定在 X1 和 Y2 中,我们可以继续在 X1 和 Y2 中递归地寻找中位数递归的终止条件是数组长度为 1 或 2。 代码实现: ```c #include <stdio.h> int findMedian(int X[], int Y[], int n) { if (n == 1) { return X[0] < Y[0] ? X[0] : Y[0]; } else if (n == 2) { int a = X[0] < Y[0] ? X[0] : Y[0]; int b = X[1] > Y[1] ? X[1] : Y[1]; return (a + b) / 2; } int m1 = X[n/2]; int m2 = Y[n/2]; if (m1 == m2) { return m1; } else if (m1 < m2) { return findMedian(X + n/2, Y, n - n/2); } else { return findMedian(X, Y + n/2, n - n/2); } } int main() { int X[] = {1, 3, 5, 7, 9}; int Y[] = {2, 4, 6, 8, 10}; int n = sizeof(X) / sizeof(X[0]); int median = findMedian(X, Y, n); printf("The median is %d\n", median); return 0; } ``` 代码解释: 函数 `findMedian` 接受三个参数:个已排好序的数组 X 和 Y,以及数组长度 n。函数的返回值是这个数组的中位数。 如果数组长度为 1,直接返回 X 和 Y 中较小的那个数作为中位数。 如果数组长度为 2,找出 X 和 Y 中各自的最大值和最小值,然后计算它们的平均值作为中位数。 如果数组长度大于 2,找出 X 和 Y 中间的个数 m1 和 m2,如果 m1 = m2,则它们就是整个数组的中位数。否则,如果 m1 < m2,则中位数一定在 X2 和 Y1 中,我们可以继续在 X2 和 Y1 中递归地寻找中位数。如果 m1 > m2,则中位数一定在 X1 和 Y2 中,我们可以继续在 X1 和 Y2 中递归地寻找中位数递归的终止条件是数组长度为 1 或 2。 在 `main` 函数中,我们定义了个已排好序的数组 X 和 Y,以及数组长度 n。然后调用 `findMedian` 函数来寻找这个数组的中位数,并打印出结果。 测试结果: ``` The median is 5 ``` 时间复杂度分析: 由于每次递归都将数组长度减半,因此递归深度为 O(log n)。在每一层递归中,我们需要比较个数组中间的个数,因此时间复杂度为 O(1)。因此,总的时间复杂度为 O(log n)。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值