LeetCode(4) ---- Median of Two Sorted Arrays

1.Problem

There are two sorted arrays nums1 and nums2 of size m and n respectively.
Find the median of the two sorted arrays. The overall run time complexity should be O(log (m+n)).

Example 1:
nums1 = [1, 3]
nums2 = [2]

The median is 2.0
Example 2:
nums1 = [1, 2]
nums2 = [3, 4]

The median is (2 + 3)/2 = 2.5

2.Translation

给两个各自排好序的数组,然后找出他们两个中的中间值,如示例所示。然后给了时间复杂度的限制。

3.My View

出去开一个大会跑回来还有各种各样的事要做……但是还是先刷一道算法吧。

回来室友说这个很简单,然后做了n久,虽然有了想法,想法是合并->排序,说起来应该达不到n方的复杂度,但是无从下手。

然后室友说用了Python的库函数,排序(数组1+数组2)。
虽然觉得直接调库就没啥意思了,但是还是写了一个调库的,更高端的有空再研究。

class Solution {
    public double findMedianSortedArrays(int[] nums1, int[] nums2) {
        //构建新数组
         int[] nums = new int[nums1.length+nums2.length];
        //将数组合并(采用arraycopy函数)
        if(nums1.length>0&&nums2.length>0){
         System.arraycopy(nums1, 0, nums, 0, nums1.length);
         System.arraycopy(nums2, 0, nums, nums1.length, nums2.length);
        }else if(nums1.length>0&&nums2.length==0){
           System.arraycopy(nums1, 0, nums, 0, nums1.length); 
        }else if(nums2.length>0&&nums1.length==0){
            System.arraycopy(nums2, 0, nums, 0, nums2.length); 
        }
        //将数组排序(sort函数)
        Arrays.sort(nums);
        //返回结果
        return (nums[(nums.length-1)/2]+nums[nums.length/2])/2.0;
    }
}

这里主要用了arraycopy和sort函数,用来完成数组合并和排序。

当然,嗯,路过打个酱油啦!

于是抽空又写了一个能说的过去的。
不过当然不能跟大神比啦。

6KBM92FU9_L_W%1GUTI2JW.png

连大众算法都没上。

public static double findMedianSortedArrays(int[] nums1, int[] nums2) {
                 //构建新数组
             int[] nums = new int[nums1.length+nums2.length];
             int num1_len = nums1.length,num2_len = nums2.length;
             int i = 0,j = 0,k = 0;
                //调整数组访问顺序  
             if(num1_len > num2_len){
                 return findMedianSortedArrays(nums2,nums1);
             }      
            while(i<num1_len||j<num2_len){
                 //余数据处理  
             if(i<=nums1.length-1&&j>nums2.length-1){
                 nums[k] = nums1[i];
                 i++;
                 k++;
                 continue;
             } 
             if(i>nums1.length-1&&j<=nums2.length-1){
                 nums[k] = nums2[j];
                 j++;
                 k++;
                 continue;
             }  
                 //正常数据处理
             if(nums1[i]<=nums2[j]){
                 nums[k] = nums1[i];
                 i++;
             }else{
                 nums[k] = nums2[j];
                 j++;
             }   
             k++;
            }    
                 //结果
            return (nums[(nums.length-1)/2]+nums[nums.length/2])/2.0;
        }

期间也是遇到大大小小的错误,连续提交了几次才成功。算法的理念就是排序合并,这个想法是源自于数据结构链表合并排序的题目,以前没仔细写过,今天算是拿数组练练手了。

真正官方的,
NB的在下面。

Solution

Put left_A and left_B into one set, and put right_A and right_B into another set.

把A数组分成左右两部分,B数组也分成左右两部分。

        left_part          |        right_part
    A[0], A[1], ..., A[i-1]  |  A[i], A[i+1], ..., A[m-1]
    B[0], B[1], ..., B[j-1]  |  B[j], B[j+1], ..., B[n-1]

然后如果我们确保

//左右长度一致
len(left_part)=len(right_part)
//左部分最大值小于右部分最小值
max(left_part)≤min(right_part)

那么我们就会很轻易地得到答案
a = (max(left_part)+ min(right_part))/2

那么接下来我们要解决的问题就是如何满足这两个条件

//首先我们要求(i是A数组左部分,j是B数组左部分,m是A的长度,
//n是B的长度,那么这样很显然就是让A_left + B_left = A_right+B_right)
i+j=m−i+n−j 
//为了确保大小,我们结合刚开始给的表格来看
B[j−1]≤A[i] and A[i−1]≤B[j]

and then?

Searching i in [0,m], to find an object i such that:
//在【0,m】区间搜索一个满足条件的i
B[j−1]≤A[i]  and A[i−1]≤B[j],  where j = (m+n+1)/2 - i

这里一定要确保j是非负数,那么要求就是m要比n小,否则可能会因为m/2太大导致j是负数。

同时我们在分析这种情况的时候,不能忽视了一些极端数据,比如说空数组,重复数据等
官方给出的解释是,当我们比较这些情况的时候

B[j−1]≤A[i]  and A[i−1]≤B[j],  where j = (m+n+1)/2 - i

如果他们不存在(数据),可以直接空过去

那么在搜索的过程中就出现了三种情况

(j=0  or  i = m  or B[j−1]≤A[i]) and
i = 0 or j=n or A[i−1]≤B[j]) 
Means ii is perfect, we can stop searching.
(j > 0 and i <m and B[j−1]>A[i]) 
Means ii is too small, we must increase it.
(i>0 and j<n and A[i−1]>B[j]) 
Means ii is too big, we must decrease it.

最后是Code

 public double findMedianSortedArrays(int[] A, int[] B) {
        //获取长度
        int m = A.length;
        int n = B.length;
        //确保长度m<n(当然在这里我们也可以用递归来实现,不过效率会低一点)
        if (m > n) { 
            int[] temp = A; A = B; B = temp;
            int tmp = m; m = n; n = tmp;
        }
        //初始化变量
        int iMin = 0, iMax = m, halfLen = (m + n + 1) / 2;
        //循环检查A数组
        while (iMin <= iMax) {
            //i是A数组中心
            int i = (iMin + iMax) / 2;
            //J也就是我们公式里的j
            int j = halfLen - i;
            //接下来就是我们的三种情况
            //通过调整imin和imax两个值来确定i,j的位置,
            //也就是确保分片的合理性
            if (i < iMax && B[j-1] > A[i]){
                iMin = iMin + 1; // i is too small
            }
            else if (i > iMin && A[i-1] > B[j]) {
                iMax = iMax - 1; // i is too big
            }
             //当i是一个合适的切片点的时候,开始查找右片最小值和左片最大值
            else { // i is perfect
                int maxLeft = 0;
                if (i == 0) { maxLeft = B[j-1]; }
                else if (j == 0) { maxLeft = A[i-1]; }
                else { maxLeft = Math.max(A[i-1], B[j-1]); }
                //奇数个直接返回中心点
                if ( (m + n) % 2 == 1 ) { return maxLeft; }

                int minRight = 0;
                if (i == m) { minRight = B[j]; }
                else if (j == n) { minRight = A[i]; }
                else { minRight = Math.min(B[j], A[i]); }
               //返回中值
                return (maxLeft + minRight) / 2.0;
            }
        }
        return 0.0;
    }

这个算法核心的地方还是在于分片。
同时这个算法也源自于高中的中值概念,通过排除最小最大值来得到中值。

更多优秀算法建议去LeetCode查看。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,732评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,496评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,264评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,807评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,806评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,675评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,029评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,683评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,704评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,666评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,773评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,413评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,016评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,204评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,083评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,503评论 2 343

推荐阅读更多精彩内容