{"id":18,"date":"2018-06-08T00:00:47","date_gmt":"2018-06-08T00:00:47","guid":{"rendered":"https:\/\/sinyalee.com\/essays\/?p=18"},"modified":"2024-09-02T03:24:41","modified_gmt":"2024-09-02T03:24:41","slug":"leetcode-hard-4-median-of-two-sorted-arrays","status":"publish","type":"post","link":"https:\/\/sinyalee.com\/essays\/?p=18","title":{"rendered":"[LeetCode HARD] 4 Median of Two Sorted Arrays"},"content":{"rendered":"<p>LeetCode has become the de facto go-to website for tech interviews. As a former competitive programmer, the LeetCode \u201chard\u201d, \u201cmedium\u201d, and \u201ceasy\u201d problems are more like \u201ceasy\u201d, \u201cvery easy\u201d, \u201cextremely easy\u201d for me. I think it would be a good idea for me to put my solutions of some of the LeetCode hard problems here. Hope it would be helpful for people who are preparing for tech interviews.<\/p>\n<p>This is my first LeetCode solution article, for\u00a0<a href=\"https:\/\/leetcode.com\/problems\/median-of-two-sorted-arrays\/\">LeetCode Problem 4, Medium of Two Sorted Arrays<\/a>.<\/p>\n<h3>Problem<\/h3>\n<p>The problem is simple: given two sorted integer arrays, find the medium element of the elements from the two arrays combined.<\/p>\n<h3>Solution<\/h3>\n<p>First, instead of finding the medium of the elements, we can solve a generalized version of this problem: giving two sorted arrays, find the\u00a0<em>k<\/em>-th smallest element for any\u00a0<em>k<\/em>.<\/p>\n<p>Now assume that\u00a0<em>k<\/em>-th element is smaller or equal to the medium. Consider the two medium elements of both arrays,\u00a0<em>m_1<\/em>\u00a0and\u00a0<em>m_2<\/em>, if\u00a0<em>m_1 &gt;= m_2<\/em>, we know that any element\u00a0<em>e<\/em>\u00a0after\u00a0<em>m_1<\/em>\u00a0in array 1 would be\u00a0<em>&gt;= m_1 &gt;= m_2<\/em>. Thus all those elements would be larger than all elements before\u00a0<em>m_1<\/em>\u00a0in array 1 and all elements before\u00a0<em>m_2<\/em>\u00a0in the second array, which are half of all elements. Thus\u00a0<em>e<\/em>\u00a0is larger than the medium and can\u2019t be the solution. Thus we can eliminate all element\u00a0<em>e<\/em>, i.e., all elements after\u00a0<em>m_1<\/em>\u00a0in array 1.<\/p>\n<p>Similarly, we can eliminate half of the elements in array 2 if\u00a0<em>m_1 &lt;= m_2<\/em>. And similarly, if the\u00a0<em>k<\/em>-th element is larger than the medium, we can eliminate the first half of array 1 or array 2.<\/p>\n<p>In every iteration, we can either eliminate half of the elements in array 1 or eliminate half of the elements in array 2. Therefore, in O(log(m)+log(n)) = O(log(m+n)) iteration, we can reduce one of the arrays to length 1, in which case we can fine the solution in O(1) time.<\/p>\n<h5>Note<\/h5>\n<p>The algorithm and the proofs above are not rigid. I prefer to focus on the core idea of the algorithm instead of wasting time on the details which would make the this article incomprehensible. You can see the source code in the end if you are interested in implementation details.<\/p>\n<h3>Takeaway<\/h3>\n<p>There are two takeaways of solving this problem. The first one is finding a generalized problem so that we can find a recursive solution. It\u2019s hard to find a recursive relation between finding the medium of two longer arrays and finding the medium of two shorter arrays. But it\u2019s easier to find the relationship between finding the\u00a0<em>k<\/em>-th element of two longer arrays and the\u00a0<em>k\u2019<\/em>-th element between two shorter arrays.<\/p>\n<p>The second one is how to find the recursive step. If we can reduce the size of the problem to\u00a0<strong>any<\/strong>\u00a0fraction of the original size in constant time, we can find a\u00a0<em>O(log(n))<\/em>\u00a0solution. We don\u2019t have to reduce the size of the problem by half. In this particular problem, we only reduce half of the elements in one of the two arrays, about 1\/4 of the total elements. But this algorithm is still\u00a0<em>O(log(n))<\/em>.<\/p>\n<h3>Source Code<\/h3>\n<p>My solution is posted below. I write it in good old C because it\u2019s easier to pass sub-arrays, and I am confident that getting a sub-array in C is O(1) without looking up the documents.<\/p>\n<pre><code class=\"language-c\">\nint findElement(int* nums1, int nums1Size, int* nums2, int nums2Size, int k) {\n    \/\/ We make sure the first array is longer than the second array \n    \/\/ to make our lives easier later.\n    if (nums1Size &gt; nums2Size)\n        return findElement(nums2, nums2Size, nums1, nums1Size, k);\n    \n    \/\/ base cases\n    if (nums1Size == 0)\n        return nums2[k];\n    if (nums1Size == 1) {\n        int e = nums1[0];\n        if (k == 0)\n            return (e &lt; nums2[0]) ? e : nums2[0]; if (k &gt;= nums2Size) \n            return (e &gt; nums2[nums2Size - 1]) ? e : nums2[nums2Size - 1];\n        if (e &gt;= nums2[k]) {\n            return nums2[k];\n        }\n        return (e &gt;= nums2[k-1]) ? e : nums2[k-1];\n    }\n    \n    \/\/ induction step\n    if (k + k &lt;= nums1Size + nums2Size) {\n        if (nums1[nums1Size\/2] &lt; nums2[nums2Size\/2])\n            return findElement(nums1, nums1Size, nums2, (nums2Size+1) \/ 2, k);\n        else\n            return findElement(nums1, (nums1Size+1) \/ 2, nums2, nums2Size, k);\n    }\n    else {\n        if ( nums1[(nums1Size-1) \/ 2] &lt; nums2[(nums2Size-1) \/ 2] ) \n            return findElement(&amp;nums1[nums1Size\/2], (nums1Size+1) \/ 2, \n                nums2, nums2Size, k - nums1Size\/2);\n        else\n            return findElement(nums1, nums1Size, \n                &amp;nums2[nums2Size\/2], (nums2Size+1) \/ 2, k - nums2Size\/2);\n    }\n}\n\ndouble findMedianSortedArrays(int* nums1, int nums1Size, int* nums2, int nums2Size) {\n    \/\/ if there are even number of elements, we need to find \n    \/\/ the average of the two medium elements.\n    int total = nums1Size + nums2Size;\n    if (total &amp; 1)\n        return (double)findElement(nums1, nums1Size, nums2, nums2Size, total\/2 );\n    else \n        return ((double)findElement(nums1, nums1Size, nums2, nums2Size, total\/2-1 ) + \n            (double)findElement(nums1, nums1Size, nums2, nums2Size, total\/2) ) \/ 2.;\n}\n\n<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>LeetCode has become the de facto go-to website for tech interviews. As a former competitive programmer, the LeetCode \u201chard\u201d, \u201cmedium\u201d, and \u201ceasy\u201d problems are more like \u201ceasy\u201d, \u201cvery easy\u201d, \u201cextremely easy\u201d for me. I think it would be a good idea for me to put my solutions of some of the LeetCode hard problems here. [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[8],"tags":[],"class_list":["post-18","post","type-post","status-publish","format-standard","hentry","category-coding"],"_links":{"self":[{"href":"https:\/\/sinyalee.com\/essays\/index.php?rest_route=\/wp\/v2\/posts\/18","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/sinyalee.com\/essays\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/sinyalee.com\/essays\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/sinyalee.com\/essays\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/sinyalee.com\/essays\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=18"}],"version-history":[{"count":5,"href":"https:\/\/sinyalee.com\/essays\/index.php?rest_route=\/wp\/v2\/posts\/18\/revisions"}],"predecessor-version":[{"id":131,"href":"https:\/\/sinyalee.com\/essays\/index.php?rest_route=\/wp\/v2\/posts\/18\/revisions\/131"}],"wp:attachment":[{"href":"https:\/\/sinyalee.com\/essays\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=18"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/sinyalee.com\/essays\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=18"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/sinyalee.com\/essays\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=18"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}