计算机中的算法到底研究的是技巧还是一种思维方式。
分析算法已知条件如下: - 两个有序数组 - 中位数:奇数取中间值偶数取中间两个数的平均数(浮点型)
报错:运行时间超时。在本程序中已经尽量只遍历对数组只遍历一次,能优化的点只有第三个函数。
本以为时间复杂度为O(n)的算法已经接近极致了,没想到其实对有序数列来说O(logN),O(1)都是可以优化的目标。到网上翻了一些算法解决方案,主要思路如下:
将找中位数抽象为找第k小的数,既然已经告知两个数组有序,那就要充分利用此有效信息,减少算法的遍历范围。缩小范围从二分法开始:两边同时二分法,A[k/2]与B[k/2]进行比较,较小者的前半段可以不再比较,以此类推,逐渐跳跃式的减少对搜索空间的遍历。
看到我的第三个函数我只想说业务代码写多了,脑子里都是渣呀。优化后的算法如下:
public class Solution { public double findMedianSortedArrays(int A[], int B[]) { int len = A.length + B.length; if (len % 2 == 1) { return findKth(A, 0, B, 0, len / 2 + 1); } return ( findKth(A, 0, B, 0, len / 2) + findKth(A, 0, B, 0, len / 2 + 1) ) / 2.0; } // find kth number of two sorted array public static int findKth(int[] A, int A_start, int[] B, int B_start, int k){ if (A_start >= A.length) { return B[B_start + k - 1]; } if (B_start >= B.length) { return A[A_start + k - 1]; } if (k == 1) { return Math.min(A[A_start], B[B_start]); } int A_key = A_start + k / 2 - 1 < A.length ? A[A_start + k / 2 - 1] : Integer.MAX_VALUE; //此处为算法的技巧点, //本质比较的是第k/2个数,当index越界时,认为其中位数为最大整数,不在此轮进行比较A数组的元素,而是去比较B数组的元素,从而减小K的取值。 //最大整数的引用,可以规范算法的形式,思想以后可以借鉴 int B_key = B_start + k / 2 - 1 < B.length ? B[B_start + k / 2 - 1] : Integer.MAX_VALUE; if (A_key < B_key) { return findKth(A, A_start + k / 2, B, B_start, k - k / 2); } else { return findKth(A, A_start, B, B_start + k / 2, k - k / 2); } } }优化算法来源:http://www.jiuzhang.com/solutions/median-of-two-sorted-arrays/
