一.问题引入
问题描述
设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);
}
}
}
}