困难-4. 寻找两个正序数组的中位数
这题难了我几天,重写了几遍代码,一直感觉不对,算法复杂度没降下来,直到今天10月7日完成
### 解题思路
不停判断区间1是否相交区间2
假如中位数存在num1中,不停地对nums1取中间值,在nums2中找,直到找到为止
假如找不到,那么最后区间1和区间2不会相交
执行结果:通过
执行用时:168 ms, 在所有 JavaScript 提交中击败了11.10%的用户
内存消耗:50.8 MB, 在所有 JavaScript 提交中击败了10.32%的用户
通过测试用例:2094 / 2094
给定两个大小分别为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。请你找出并返回这两个正序数组的 中位数 。
算法的时间复杂度应该为 O(log (m+n)) 。
示例 1:
输入:nums1 = [1,3], nums2 = [2]
输出:2.00000
解释:合并数组 = [1,2,3] ,中位数 2
示例 2:
输入:nums1 = [1,2], nums2 = [3,4]
输出:2.50000
解释:合并数组 = [1,2,3,4] ,中位数 (2 + 3) / 2 = 2.5
提示:
nums1.length == m
nums2.length == n
0 <= m <= 1000
0 <= n <= 1000
1 <= m + n <= 2000
-106 <= nums1[i], nums2[i] <= 106
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/median-of-two-sorted-arrays
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
/** * @param {number[]} nums1 * @param {number[]} nums2 * @return {number} */ var findMedianSortedArrays = function(nums1, nums2) { //例如:求一个考生在全国的排名p,分数为num //先用二分法求考生在各省的排名p1、p2...pn //分数num在全国的排名p=p1+p2+..+pn //如果中位数比排名p大,以当前考生为最左边,继续上一步的查找 //如果中位数比排名p小,以当前考生为最右边,继续上一步的查找 //如果中位值等于排名p,那这个考生就是全国排名的中位数 let l1=0,r1=nums1.length; let l2=0,r2=nums2.length; let isLock=true; let len=nums1.length+nums2.length const isTwo=len%2===0 const needMid=len>>1 let ans1 let ans2 while(isLock){ console.log(l1,r1,l2,r2) //区间有交叉 if(l1===r1||nums1[r1-1]<=nums2[l2]){ isLock=false if(r1>needMid-l2){ ans1=nums1[needMid-l2] }else{ ans1=nums2[needMid-r1] } if(r1>needMid-1-l2){ ans2=nums1[needMid-1-l2] }else{ ans2=nums2[needMid-r1-1] } console.log(ans1,ans2) }else if(l2===r2||nums2[r2-1]<=nums1[l1]){ isLock=false if(r2>needMid-l1){ ans1=nums2[needMid-l1] }else{ ans1=nums1[needMid-r2] } if(r2>needMid-1-l1){ ans2=nums2[needMid-l1-1] }else{ ans2=nums1[needMid-r2-1] } console.log(ans1,ans2) }else{ const mid=(l1+r1)>>1 //获取排名 const [p1,p2]=getScope(nums1[mid],nums2,l2,r2); if(mid+p1>needMid){ r1=mid r2=p1 }else if(mid+p2<needMid){ l1=mid l2=p2 }else{ isLock=false //在nums1中找到 ans1=nums1[mid] if(needMid-mid>0&&mid>0){ ans2=Math.max(nums1[mid-1],nums2[needMid-mid-1]) }else if(mid>0){ ans2=nums1[mid-1] }else{ ans2=nums2[needMid-mid-1] } } } } console.log(l1,r1,l2,r2,needMid) if(isTwo){ return (ans1+ans2)/2 } return ans1 //获取数字在数组中的区域[左边,右边] function getScope(num,arr,l,r){ let lock=true while(lock&&l<r){ const m=(l+r)>>1 if(arr[m]>num){ r=Math.min(m,r-1); }else if(arr[m]<num){ l=Math.max(m,l+1); }else{ l=m; r=m+1; while(arr[l-1]===arr[m]){ l-- } while(arr[r]===arr[m]){ r++ } lock=false; } } return [l,r]; } };