分治法求解两个数组的中位数

一.问题引入

问题描述

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

编程任务

利用分治策略试设计一个O (log n)时间的算法求出这2n个数的中位数。第1行中有1个正整数n(n<=200),表示每个数组有n个数。接下来的两行分别是X,Y数组的元素。

结果输出

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

二.算法实现(C++) 

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
float searchMid(int a[], int b[], int n, int aL, int bL, int aR, int bR) {
	float aMid, bMid;//数组a,b的中位数
	int aIndex, bIndex;//数组a,b的中位数的数组序号

	if (aR == aL) {
		return (a[aR] + b[bR]) / 2.0;
	}

	if ((aR - aL) % 2 == 0) {
		aMid = a[(aR + aL) / 2] / 1.0;
		bMid = b[(bR + bL) / 2] / 1.0;
		aIndex = (aR + aL) / 2;
		bIndex = (bR + bL) / 2;

		if (aMid == bMid) {
			return aMid;
		}
		else if (aMid < bMid) {
			return searchMid(a, b, n, aIndex, bL, aR, bIndex);
		}
		else {
			return searchMid(a, b, n, aL, bIndex, aIndex, bR);
		}
	}
	else {
		aMid = (a[(aR + aL + 1) / 2] + a[(aR + aL + 1) / 2 - 1]) / 2.0;
		bMid = (b[(bR + bL + 1) / 2] + b[(bR + bL + 1) / 2 - 1]) / 2.0;
		aIndex = (aR + aL + 1) / 2;
		bIndex = (bR + bL + 1) / 2;

		if (aMid == bMid) {
			return aMid;
		}
		else if (aMid < bMid) {
			if (a[aIndex] <b[bIndex] && a[aIndex - 1] > b[bIndex - 1]) {
				return aMid;
			}
			else if (a[aIndex] > b[bIndex] && a[aIndex - 1] < b[bIndex - 1]) {
				return bMid;
			}
			else {
				return searchMid(a, b, n, aIndex, bL, aR, bIndex - 1);
			}
		}
		else {
			if (a[aIndex] < b[bIndex] && a[aIndex - 1] > b[bIndex - 1]) {
				return aMid;
			}
			else if (a[aIndex] > b[bIndex] && a[aIndex - 1] < b[bIndex - 1]) {
				return bMid;
			}
			else {
				return searchMid(a, b, n, aL, bIndex, aIndex - 1, bR);
			}
		}
	}
}

int main() {
	int a[100], b[100];
	int n;
	cout << "请输入数组的长度:" << endl;
	cin >> n;
	cout << "请依次输入数组a的值:" << endl;
	for (int i = 0; i < n; i++) {
		cin >> a[i];
	}
	cout << "请依次输入数组b的值:" << endl;
	for (int j = 0; j < n; j++) {
		cin >> b[j];
	}
	cout << "中位数是:" << endl;
	cout << searchMid(a, b, n, 0, 0, n - 1, n - 1);
}

结果实现:

 

 

三.算法实现(Python) 

def find_kth_element(X, Y, k):
    if not X:
        return Y[k]
    if not Y:
        return X[k]

    mid_X = len(X) // 2
    mid_Y = len(Y) // 2

    if mid_X + mid_Y < k:
        if X[mid_X] > Y[mid_Y]:
            return find_kth_element(X, Y[mid_Y + 1:], k - mid_Y - 1)
        else:
            return find_kth_element(X[mid_X + 1:], Y, k - mid_X - 1)
    else:
        if X[mid_X] > Y[mid_Y]:
            return find_kth_element(X[:mid_X], Y, k)
        else:
            return find_kth_element(X, Y[:mid_Y], k)

print("请输入数组的长度:")
n=int(input())
if n!=0:
    print("请依次输入数组a的值:")
    X=list(map(int,input().split(" ")))

    print("请依次输入数组b的值:")
    Y=list(map(int,input().split(" ")))

    num1=find_kth_element(X,Y,n-1)
    num2=find_kth_element(X,Y,n)

    print("中位数是:")
    if (num1+num2)/2==int((num1+num2)/2):
        print(int((num1+num2)/2))
    else :
        print((num1+num2)/2)

结果实现:

 

 

四.算法实现(Java)

package suanfa;

import java.util.Arrays;
import java.util.Scanner;
import java.util.Scanner;

public class suanfa {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        System.out.print("请输入数组的长度:");
        int n = scanner.nextInt();

        if (n != 0) {
            System.out.println("请依次输入数组a的值:");
            int[] X = new int[n];
            for (int i = 0; i < n; i++) {
                X[i] = scanner.nextInt();
            }

            System.out.println("请依次输入数组b的值:");
            int[] Y = new int[n];
            for (int i = 0; i < n; i++) {
                Y[i] = scanner.nextInt();
            }

            int num1 = findKthElement(X, Y, n - 1);
            int num2 = findKthElement(X, Y, n);

            System.out.println("中位数是:");
            if ((num1 + num2) % 2 == 0) {
                System.out.println((num1 + num2) / 2);
            } else {
                System.out.println((num1 + num2) / 2.0);
            }
        }
    }

    private static int findKthElement(int[] X, int[] Y, int k) {
        if (X.length == 0) {
            return Y[k];
        }
        if (Y.length == 0) {
            return X[k];
        }

        int midX = X.length / 2;
        int midY = Y.length / 2;

        if (midX + midY < k) {
            if (X[midX] > Y[midY]) {
                return findKthElement(X, Arrays.copyOfRange(Y, midY + 1, Y.length), k - midY - 1);
            } else {
                return findKthElement(Arrays.copyOfRange(X, midX + 1, X.length), Y, k - midX - 1);
            }
        } else {
            if (X[midX] > Y[midY]) {
                return findKthElement(Arrays.copyOfRange(X, 0, midX), Y, k);
            } else {
                return findKthElement(X, Arrays.copyOfRange(Y, 0, midY), k);
            }
        }
    }
}

 

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值