# 题目

4. Median of Two Sorted Arrays

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 = [, ]
nums2 = []

The median is 2.0

Example 2:

nums1 = [, ]
nums2 = [, ]

The median  + )/ = 2.5

# 思路

两指针填充数组法:

想法来源于插入排序的过程。插入排序每一次将一位数字之前插入有序数组之中。

例如{1, 3, 4, 2},前面三位已用插入排序排序完毕,第四位2首先和1比较,大于,再和后面一位比较,小于,故放入该位置,其余元素后移。

此题的算法:

首先,把指针index1指向nums1,指针Index2指向nums2,同时创建一个数组sum,用来保存两个数组按照大小合并的结果。

接着,比较index1和index2所指元素的大小,sum数组填充两者较小的一个,同时指向较小元素的指针后移一位。

反复上面一步,当sum填充到中间时,结束,根据奇偶,计算中间值。

举个例子:

比如nums1 = {1, 3},nums2 = {2, 4, 5},index1指向nums1中的1,index2指向nums2中的2,1 < 2,所以sum填充1。

此时index1后移指向3,3 > 2,sum填充2,index2后移。此时index2指向4,4 > 3,sum填充3。此时sum已经填充到中部,故直接输出3。

        // use two pointers to construct full nums including nums1 and nums2
        // two pointers: time O(m+n) space O(n) result: 255ms
        public double FindMedianSortedArrays(int[] nums1, int[] nums2)
        {
            int[] sum;
            // nums1 is null or num2 is null
            if (nums1.Length == 0) sum = nums2;
            else if (nums2.Length == 0) sum = nums1;
            else sum = new int[nums1.Length + nums2.Length];

            // user 2 pointers to find middle numbers
            int length = nums1.Length + nums2.Length, index1 = 0, index2 = 0, index = 0;
            for (; index < sum.Length && index1 < nums1.Length && index2 < nums2.Length; index++)
            {
                if (nums1[index1] < nums2[index2]) sum[index] = nums1[index1++];
                else sum[index] = nums2[index2++];
            }
            for (; index1 < nums1.Length; index++, index1++)
                sum[index] = nums1[index1];
            for (; index2 < nums2.Length; index++, index2++)
                sum[index] = nums2[index2];

            if (length % 2 != 0) return sum[length / 2];
            else return (double)(sum[length / 2 - 1] + sum[length / 2]) / 2;
        }

两指针填充数组法时间复杂度O(m + n)空间复杂度O(n)时间255ms

算法虽然AC(Accept)了,可并不满足题中所给的时间复杂度O(lg(m + n))。谈到lg,即以2为底的对数,很容易联想到对半的思想,二分查找法。

然而我并想不出来如何二分。

去LeetCode的Discuss区看了一下。发现了这样一个算法:二分查找,划分两数组法。参考地址:https://discuss.leetcode.com/topic/4996/share-my-o-log-min-m-n-solution-with-explanation/90。

天才。

只说说大概流程,具体内容直接参考链接,不懂请大胆留言。

算法的主要目的是将nums1和nums2形式意义上合并,再划分成两个规模相等右侧所有数字大于左侧所有数字的数组(利用指针标记划分的位置),再根据划分的位置(由于两部分规模相等,必然是中间元素),输出结果。

如下图,我们先确定划分位置,这个划分位置一定会将左右两侧等分。

之后我们要保证左侧所有元素小于右侧所有元素,由于nums1和nums2是有序数组,边界元素就是划分之中最大/最小的元素,所以我们只需要关注边界即可。

假设nums1划分的位置是i,nums2划分的位置是j,要满足左侧元素小于右侧所有元素,必须满足nums1[i - 1] < nums1[i](数组有序,必定满足),nums1[i - 1] < nums2[j],nums1[i] > nums2[j - 1],nums2[j - 1] < nums2[j](数组有序,必定满足)。

若不满足nums1[i - 1] < nums2[j],如图,重新确定划分位置(图只是重划分的位置只是减少了1,实际上重划分的位置采用二分法)。

若不满足nums1[i] > nums2[j - 1],如图,重新确定划分位置(图只是重划分的位置只是减少了1,实际上重划分的位置采用二分法)。


反复上述过程,最后我们可以得到中间值。

# 解决(二分查找,划分两数组法)

        // reference: https://discuss.leetcode.com/topic/4996/share-my-o-log-min-m-n-solution-with-explanation/
        // time: O(lg(min(nums1,nums2)) space: O(1) result: 228ms
        public double FindMedianSortedArrays(int[] nums1, int[] nums2)
        {
             && nums2.Length == ) throw new Exception("none value in nums1 and nums2");
             && nums2.Length %  == )  - ] + nums2[nums2.Length / ]) / ;
             && nums2.Length %  != ) ];
             && nums1.Length %  == )  - ] + nums1[nums1.Length / ]) / ;
             && nums1.Length %  != ) ];
            if (nums1.Length > nums2.Length) return FindMedianSortedArrays(nums2, nums1);
            , imax = nums1.Length, midLength = (nums1.Length + nums2.Length + ) / ;
            int i, j;

            // when i isn't the split must satisfy below condition
            do
            {
                i = (imin + imax) / ;
                j = midLength - i;
                 && j < nums2.Length && nums1[i - ] > nums2[j]) imax--; // nums[i - 1] > nums[j] means imin is too samll
                 && nums1[i] < nums2[j - ]) imin++; // nums1[i] < nums2[j - 1] means imax is small
                else break;
            }
            while (true);

            // i is split, so we get answer by conditon
            // get left first
            int left;
            ) left = nums2[j - ];
            ) left = nums1[i - ];
            ] > nums2[j - ] ? nums1[i - ] : left = nums2[j - ];

            // sum length is odd
             != )
            {
                return (double)left;
            }
            else
            {
                int right;
                if (i == nums1.Length) right = nums2[j];
                else if (j == nums2.Length) right = nums1[i];
                else right = nums1[i] < nums2[j] ? nums1[i] : nums2[j];
                ;
            }
        }

二分查找,划分两数组法时间复杂度O(lg(m + n))空间复杂度O(1)时间228ms

# 题外话

图够丑吗?来喷我啊,嘿嘿?

# 测试用例

        static void Main(string[] args)
        {
            _4MedianofTwoSortedArrays solution = new _4MedianofTwoSortedArrays();
            Debug.Assert(solution.FindMedianSortedArrays(,  },  }) == 2.0d, "wrong 1"); // odd
            Debug.Assert(solution.FindMedianSortedArrays( }, ,  }) == 2.0d, "wrong 2"); // odd
            Debug.Assert(solution.FindMedianSortedArrays(,  }, ,  }) == 2.0d, "wrong 3"); // even and duplication
            Debug.Assert(solution.FindMedianSortedArrays(,  }, ,  }) == 2.5d, "wrong 4"); // even
            Debug.Assert(solution.FindMedianSortedArrays(,  }) == 3.5d, "wrong 5"); // nums1 null
            Debug.Assert(solution.FindMedianSortedArrays(,  }, new int[] { }) == 2d, "wrong 6"); // nums2 numm
            Debug.Assert(solution.FindMedianSortedArrays(, , , , ,  },  }) == 4d, "wrong 7"); // only nums1 pointer move
            Debug.Assert(solution.FindMedianSortedArrays( }, , , , , , ,  }) == 4.5d, "wrong 8"); // only nums2 pointer move
            Debug.Assert(solution.FindMedianSortedArrays(, ,  }, , , , ,  }) == 3.5d, "wrong 9");
            Debug.Assert(solution.FindMedianSortedArrays(,  }, , , , ,  }) == 3d, "wrong 10");
        }

# 地址

Q: https://leetcode.com/problems/median-of-two-sorted-arrays/

A: https://github.com/mofadeyunduo/LeetCode/tree/master/4MedianofTwoSortedArrays

(希望各位多多支持本人刚刚建立的GitHub和博客,谢谢,有问题可以邮件609092186@qq.com或者留言,我尽快回复)

LeetCode-4MedianofTwoSortedArrays(C#)的更多相关文章

  1. 我为什么要写LeetCode的博客?

    # 增强学习成果 有一个研究成果,在学习中传授他人知识和讨论是最高效的做法,而看书则是最低效的做法(具体研究成果没找到地址).我写LeetCode博客主要目的是增强学习成果.当然,我也想出名,然而不知 ...

  2. LeetCode All in One 题目讲解汇总(持续更新中...)

    终于将LeetCode的免费题刷完了,真是漫长的第一遍啊,估计很多题都忘的差不多了,这次开个题目汇总贴,并附上每道题目的解题连接,方便之后查阅吧~ 477 Total Hamming Distance ...

  3. [LeetCode] Longest Substring with At Least K Repeating Characters 至少有K个重复字符的最长子字符串

    Find the length of the longest substring T of a given string (consists of lowercase letters only) su ...

  4. Leetcode 笔记 113 - Path Sum II

    题目链接:Path Sum II | LeetCode OJ Given a binary tree and a sum, find all root-to-leaf paths where each ...

  5. Leetcode 笔记 112 - Path Sum

    题目链接:Path Sum | LeetCode OJ Given a binary tree and a sum, determine if the tree has a root-to-leaf ...

  6. Leetcode 笔记 110 - Balanced Binary Tree

    题目链接:Balanced Binary Tree | LeetCode OJ Given a binary tree, determine if it is height-balanced. For ...

  7. Leetcode 笔记 100 - Same Tree

    题目链接:Same Tree | LeetCode OJ Given two binary trees, write a function to check if they are equal or ...

  8. Leetcode 笔记 99 - Recover Binary Search Tree

    题目链接:Recover Binary Search Tree | LeetCode OJ Two elements of a binary search tree (BST) are swapped ...

  9. Leetcode 笔记 98 - Validate Binary Search Tree

    题目链接:Validate Binary Search Tree | LeetCode OJ Given a binary tree, determine if it is a valid binar ...

  10. Leetcode 笔记 101 - Symmetric Tree

    题目链接:Symmetric Tree | LeetCode OJ Given a binary tree, check whether it is a mirror of itself (ie, s ...

随机推荐

  1. Linux 内核概述 - Linux Kernel

    Linux 内核学习笔记整理. Unix unix 已有40历史,但计算机科学家仍认为其是现存操作系统中最大和最优秀的系统,它已成为一种传奇的存在,历经时间的考验却依然声名不坠. 1973 年,在用 ...

  2. 使用struct处理二进制

    有的时候需要用python处理二进制数据,比如,存取文件.socket操作时.这时候,可以使用python的struct模块来完成. struct模块中最重要的三个函数是pack(), unpack( ...

  3. .NetCore中的日志(1)日志组件解析

    .NetCore中的日志(1)日志组件解析 0x00 问题的产生 日志记录功能在开发中很常用,可以记录程序运行的细节,也可以记录用户的行为.在之前开发时我一般都是用自己写的小工具来记录日志,输出目标包 ...

  4. 【.net 深呼吸】程序集的热更新

    当一个程序集被加载使用的时候,出于数据的完整性和安全性考虑,程序集文件(在99.9998%的情况下是.dll文件)会被锁定,如果此时你想更新程序集(实际上是替换dll文件),是不可以操作的,这时你得把 ...

  5. 冒泡,setinterval,背景图的div绑定事件,匿名函数问题

    1.会冒泡到兄弟元素么? $(function(){ $("#a").click(function(){alert("a")}) $("#b" ...

  6. 前端学HTTP之字符集

    前面的话 HTTP报文中可以承载以任何语言表示的内容,就像它能承载图像.影片或任何类型的媒体那样.对HTTP来说,实体主体只是二进制信息的容器而已.为了支持国际性内容,服务器需要告知客户端每个文档的字 ...

  7. 基于AOP的MVC拦截异常让代码更优美

    与asp.net 打交道很多年,如今天微软的优秀框架越来越多,其中微软在基于mvc的思想架构,也推出了自己的一套asp.net mvc 框架,如果你亲身体验过它,会情不自禁的说‘漂亮’.回过头来,‘漂 ...

  8. 用神奇的currentColor制作简洁的颜色动画效果

    先上一个兼容性总结图:老版本ie可以直接用复杂方法了,套用某表情包的话:  2016年了,做前端你还考虑兼容IE6?你这简直是自暴自弃! 好了,知道了兼容性,我们可以放心的使用了. 在CSS3中扩展了 ...

  9. C++随笔:.NET CoreCLR之GC探索(3)

    有几天没写GC相关的文章了哈,今天我讲GC的方式是通过一个小的Sample来讲解,这个小的示例代码只有全部Build成功了才会有.地址为D:\coreclr2\coreclr\bin\obj\Wind ...

  10. 火星坐标、百度坐标、WGS-84坐标相互转换及墨卡托投影坐标转经纬度JavaScript版

    火星坐标 火星坐标是国家测绘局为了国家安全在原始坐标的基础上进行偏移得到的坐标,基本国内的电子地图.导航设备都是采用的这一坐标系或在这一坐标的基础上进行二次加密得到的.火星坐标的真实名称应该是GCJ- ...