问题:
给定两个有序数组a,b,长度都为n,求解两个有序数组中第K大的数。
分析:
对于所有的这种问题,我们首先想到缩减问题的规模,但是缩减后,求解对象依旧不变,保持一致性,我们首先找到彼此的中位数,判断中位数之间的大小,设a的中位数为x,b的中位数为y,如果x+y>k,那么所有b中的y和大于y的数都大于k,删除不影响问题规模;如果x+y<k,那么删除a中x和x之前的数字,并且将k减小到k-x,在剩余中查找第k-x大的数字,递归查找下去。
代码如下:
/* * findMedian.cpp * * Created on: 2012-10-28 * Author: happier */ #include <stdio.h> #include <stdlib.h> #define N 5 int a[N] = { 1, 2, 3, 4, 5 }; int b[N] = { 4, 5, 6, 7, 8 }; //获取数组a中从s1到n1个元素 //数组b中s2到n2个元素,合并后的第k大元素 int getMedian(int s1, int n1, int s2, int n2, int k) { //x和y分别记录中间值的索引 int x, y; x = (s1 + n1) / 2; //记录a的中位数索引 y = (s2 + n2) / 2; //记录b的中位数索引 if (s1 > n1) return b[s2 + k - 1]; if (s2 > n2) return a[s1 + k - 1]; if (a[x] <= b[y]) { if (k <= (x - s1) + (y - s2) + 1) { return getMedian(s1, n1, s2, y - 1, k); } else { return getMedian(x + 1, n1, s2, n2, k - (x - s1) - 1); } } else { if (k <= (x - s1) + (y - s2) + 1) { return getMedian(s1, x - 1, s2, n2, k); } else { return getMedian(s1, n1, y + 1, n2, k - (y - s2) - 1); } } return 0; } int main() { int i; i = getMedian(0, 4, 0, 4, 8); printf("%d\n", i); return 0; }
代码转自网友
总结:
问题规模减小,但是注意修改子问题。