博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【递归打卡1】在两个长度相等的排序数组中找到上中位数
阅读量:5051 次
发布时间:2019-06-12

本文共 2603 字,大约阅读时间需要 8 分钟。

【题目】

给定两个有序数组arr1和arr2,已知两个数组的长度都为N,求两个数组中所有数的上中位数。要求时间复杂度O(logN),空间复杂度O(1)

【举例】

例如 arr1 = [1, 2,3,4],arr2 = [3,4,5,6]。

总共8个数,则中位数就是第 4 小的数,为 3.

例如 arr1 = [0,1,2],arr2 = [3,4,5]。

总共6个数,则中位数就是第 3 小的数,为 2.

【难度】

解答

这道题可以采用递归来解决,注意,这道题数组是有序的,所以它有如下特点:

(1)、当 两个数组的长度为偶数时:

我来举个例子说明他拥有的特点吧。我们假定

arr1 = [1, 2,3,4],arr2 = [3,4,5,6]。则数组的长度为 n = 4。

169863e4347a5998?w=455&h=215&f=png&s=6957

分别选出这两个数组的上中位数的下标,即

mid1 = (n-1)/2 = 1。

mid2 = (n - 1)/2 = 1。

1698642256c9a858?w=516&h=339&f=png&s=10752

假如 arr2[mid2] > arr2[mid1],那么我们要找的目标数是一定存在于 arr1[mid1+1...n] 和 arr2[0...mid2]中。而不可能存在于 arr1[0...mid1] 和 arr2[mid2+1...n] 之中。

169864ff0800b80d?w=503&h=525&f=png&s=15706

也就是说,我们接下来只需要在arr1[mid1+1...n] 和 arr2[0...mid2] 中查找就行了。

(2)、当两个数组的长度为奇数时:

假定 arr1 = [1, 2,3,4,5],arr2 = [3,4,5,6,7]。则数组的长度为 n = 5。

mid1 = (n-1)/2 = 2。

mid2 = (n - 1)/2 = 2。

这个时候如果 arr2[mid2] > arr1[mid1] 时,则和上面那个情况有点小差别,这时候目标数只存在于 arr1[mid1...n] 和 arr2[0...mid2]中。注意他们的差别,从arr1[mid1+1...n] => arr1[mid1...n]。

理解了这个原理,配合上代码会更好理解,代码如下:

public static int getUpMedian(int[] arr1, int[] arr2) {        if(arr1 == null || arr2 == null )            return -1;        // 开始寻找        return find(arr1, 0, arr1.length - 1, arr2, 0, arr2.length - 1);    }    public static int find(int[] arr1, int l1, int r1, int[] arr2, int l2, int r2) {        int mid1 = l1 + (r1 - l1) / 2;        int mid2 = l2 + (r2 - l2) / 2;        // 表示数组只剩下一个数,把两个数组中较小的数返回去        if (l1 >= r1) {            return Math.min(arr1[l1], arr2[l2]);        }        // 元素个数为奇数,则offset为0,为偶数则 offset 为 1        int offset = ((r1 - l1 + 1) & 1) ^ 1;// 用位运算比较快        if (arr1[mid1] < arr2[mid2]) {            return find(arr1, mid1+offset, r1, arr2, l2, mid2);        } else if (arr1[mid1] > arr2[mid2]) {            return find(arr1, l1, mid1, arr2, mid2 + offset, r2);        } else {            return arr1[mid1];// 返回 arr2[mid2]也可以。        }    }

也可以用迭代来做,反而更加简单,迭代版本如下:

// 迭代版本    public int getUpMedian2(int[] arr1, int[] arr2) {        if (arr1 == null || arr2 == null) {            return -1;        }        int l1 = 0;        int r1 = arr1.length - 1;        int l2 = 0;        int r2 = arr2.length - 1;        int mid1 = 0;        int mid2 = 0;        int offset = 0;        while (l1 < r1) {            mid1 = l1 + (r1 - l1) / 2;            mid2 = l2 + (r2 - l2) / 2;            offset = ((r1 - l1 + 1) & 1)^1;            if (arr1[mid1] < arr2[mid2]) {                l1 = mid1 + offset;                r2 = mid2;            } else if (arr1[mid1] > arr2[mid2]) {                r1 = mid1;                l2 = mid2 + offset;            } else {                return arr2[mid1];            }        }        return Math.min(arr1[l1], arr2[l2]);    }

1699692cd427738c?w=900&h=500&f=png&s=96630

转载于:https://www.cnblogs.com/kubidemanong/p/10562292.html

你可能感兴趣的文章
几款Http小服务器
查看>>
iOS 数组排序
查看>>
第三节
查看>>
PHP结合MYSQL记录结果分页呈现(比较实用)
查看>>
Mysql支持的数据类型
查看>>
openSuse beginner
查看>>
Codeforces 620E(线段树+dfs序+状态压缩)
查看>>
Windows7中双击py文件运行程序
查看>>
Market entry case
查看>>
bzoj1230 开关灯 线段树
查看>>
LinearLayout
查看>>
学习python:day1
查看>>
css3动画属性
查看>>
第九次团队作业-测试报告与用户使用手册
查看>>
Equal Sides Of An Array
查看>>
CentOS笔记-用户和用户组管理
查看>>
Mongodb 基本命令
查看>>
Qt中QTableView中加入Check列实现
查看>>
“富豪相亲大会”究竟迷失了什么?
查看>>
控制文件的备份与恢复
查看>>