算法---寻找两个有序数组的中间点

给定两个有序数组a1,a2,长度分别是m,n。寻找这两个数组的中间点。例如
a1 = [1, 2]
a2 = [3,4]
中点是2.5

算法思路来自https://discuss.leetcode.com/topic/16797/very-concise-o-log-min-m-n-iterative-solution-with-detailed-explanation
以下代码是kotlin版本实现

/**
 * Created by thinkreed on 2017/6/23.
 */

fun findMedianOfTwoArray(a1: Array<Int>, a2: Array<Int>): Double {

    //保证a2比a1短
    if (a1.size < a2.size) return findMedianOfTwoArray(a2, a1)

    //a2为空,返回a1的中间点
    if (a2.isEmpty()) return (a1[(a1.size - 1) / 2].toDouble() + a1[a1.size / 2].toDouble()) / 2

    var low = 0
    var high = 2 * a2.size

    //二分查找均分点
    while (low <= high) {
        //以中点切分
        val mid2 = (low + high) / 2
        //通过mid2推断mid1,若mid1和mid2是两数组的两个切分点,则满足mid1+mid2 = a1.size + a2.size
        val mid1 = a1.size + a2.size - mid2

        //L1,R1分别表示数组a1的切分点C1的左相邻元素,右相邻元素
        //L2,R2分别表示数组a2的切分点C2的左相邻元素,右相邻元素
        val L1 = if (mid1 == 0) Int.MIN_VALUE else a1[(mid1 - 1) / 2]
        val L2 = if (mid2 == 0) Int.MIN_VALUE else a2[(mid2 - 1) / 2]
        val R1 = if (mid1 == 2 * a2.size) Int.MAX_VALUE else a1[mid1 / 2]
        val R2 = if (mid2 == 2 * a2.size) Int.MAX_VALUE else a2[mid2 / 2]

        //a1的左边部分太大了,将切分点C1左移,C2相应得右移
        if (L1 > R2) low = mid2 + 1
        //a2的左边部分太大了,将切分点C2左移,C1相应右移
        else if (L2 > R1) high = mid2 - 1
        //满足条件L1<=R2 && L2<=R1
        else return (maxOf(L1, L2).toDouble() + minOf(R1, R2).toDouble()) / 2
    }

    return -1.0
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 时过境迁才领悟:世态炎凉!时间让人知道什么该珍惜、什么不属于自己失去了就算。最近这段时间,不由自己的想了很多!谁能...
    听清风梳叶阅读 283评论 1 2
  • 有时寂寞, 不是因为孤单, 再多的人, 也没有一个和我共鸣! 有时寂寞, 不是因为忧伤, 再多的快乐, 也与我无关...
    徍音_阅读 288评论 0 1
  • 我心仪的公司是新型计算机科技公司。原因也很简单,随着计算机技术的发展,人工智能的浪潮一点点逼近,想要在这个时代跟随...
    du_xzhe阅读 212评论 0 0
  • 【微公益】【618】【每日经典,伴您早起】【20170102孟子92】 【原文】 子产听郑国之政,以其乘舆济人于溱...
    北冥_鲲阅读 371评论 1 2