呕心沥血的一个题解,点赞关注在看,一键三联,一起加入我们打卡!。

题目描述:呕心沥血的一个题解,点赞关注收藏,一键三联,一起加入我们打卡!

题目描述:给定两个大小为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。

请你找出这两个正序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n))。

你可以假设 nums1 和 nums2 不会同时为空。

示例 1:nums1 = [1, 3]

nums2 = [2]

则中位数是 2.0

示例 2:nums1 = [1, 2]

nums2 = [3, 4]

则中位数是 (2 + 3)/2 = 2.5

归并法(O(m+n))

分析之前小吐槽一句,这题自己真的没想到O(log(m+n))的方法,只能想到O(m+n)的归并,没想到怎么去使用二分,后来看了题解也是才明白。但也算自己理解了和大家分享一下。

对于这个问题或许本身不难,但是可能难在O(log(m+n))的时间复杂度上。

如果真的无法想到好的方法,先想着过关,该用什么方法呢?

法一暴力法:

可以将两个数组添加到一个总的数组中,然后给这个数组进行排序。正常的排序是O(nlogn)的时间复杂度。排序之后根据奇数偶数取中位数即可。

法二归并法:

给的两个数组本身是有序的,想必熟悉归并排序的朋友们应该能一下就想出来这个方法,两个有序的.只需按照以下流程即可完成归并:待归并的两个数组分别设置两个指针leftindex,rightindex均从0开始。新数组也设置游标index。

比较两数组leftindex和rightindex位置的值,较小的那个赋值到新数组中同时新数组游标和较小的那个游标均加一。在这里插入图片描述

重复到其中一个数组遍历完,另一个数组剩余值直接加入后面即可。在这里插入图片描述

实现代码:public double findMedianSortedArrays(int[] nums1, int[] nums2){

int a[]=new int[nums1.length+nums2.length];

int lindex=0,rindex=0;

int index=0;

while (lindex

if(nums1[lindex]

{

a[index++]=nums1[lindex++];

}

else {

a[index++]=nums2[rindex++];

}

}

while (lindex

a[index++]=nums1[lindex++];

}

while (rindex

a[index++]=nums2[rindex++];

}

if(a.length%2==0)

return (double)(a[a.length/2-1]+a[a.length/2])/2;

else {

return a[a.length/2];

}

}

二分法(O(log(m+n)))

想到有序的,又是O(log(m+n))的时间复杂度,估计大部分人都能想到二分,我当时也是一样,但是该怎么想呢这就是一个问题。记录下我当初错误的想法:二分,二分找到两个中间的。然后正常有个长的,有个短的,根据两个数值比较分类推测中位数应该在哪个区间……然后大脑就断电了。

对于中位数的简单分析:如果两个数组长度和为奇数,那么最终这个中位数是由一位数确定的。

如果两个数组长度和为偶数,那么最终这个中位数是由两位数取平均值确定的。

对两个数组的简单分析:两个数组应该有一个长一点,另一个点一点(等长也不影响)。

中位数可能让两个数组都分成两部分:一部分小于中位数,一部分大于中位数。但两个部分合起来总数量应该一致。

在这里插入图片描述

对两数组和中位数位置分析:我们知道两数组虽然可能等长(不影响),但正常情况应该是一个长(m)一个短(n)。长短数组分别对应的坐标m1和n1和中位数坐标有什么关系?

无论总和奇数偶数,都满足(m1+n1)=(m+n)/2;因为两个数组都是有序的所以总共小于中位数的占一半。其中m和n是定值。也就是不管你怎么变动,这两个坐标编号是总和为定值得!

如何分析为定值得坐标既然两个坐标的总和为定值,那么可不可以把其中一个当为自变量,一个看成自变量呢?比如x+y=5你不好分析但是y=5-x,你分析x同时y就确定了。对吧?

那么选择长的那个作为变量还是短的那个作为变量呢?短的,为啥,主要因为如果从长的当成变量咱们有些区域无法对应到短的(因为长度即使加上短的所有也到不了一半,处理起来麻烦):

在这里插入图片描述

但是短的就可以很好避免这种情况:

在这里插入图片描述

所以我们就用二分去查找小的这个区间,找到最终的结果,你可能会问:什么样情况能够满足确定这条线的附近就是产生中位数的?二分进行查找编号的时候,满足左侧都比线右侧小才行。这种情况在二分查找就是一个平衡的结果。

在这里插入图片描述

最后找到这个index线了。取值比较你还要有注意的地方:取左侧的时候左侧如果有index为0,取右侧的时候index为最大值:

在这里插入图片描述

所以这种在你最后取值的时候,需要考虑左右侧是否有值。同时取长的那个也要比较,因为可能出现等长情况例如:1 2 3 4,和5 6 7 8这种去到临界。需要判断当然在实现过程用三目运算简化!

总的来说:根据短的进行二分查找位置,先找到线index,说明中位数在附近产生。(奇数偶数在查找因为要除2可以通用表达式)

如果总个数奇数,那么就是线左侧最大的那个(两个比较或只有一个)

如果总个数偶数,那么就是线左侧最大的那个(两个比较或只有一个)和线右侧最小的那个(两个比较或只有一个)的值取平均,注意是double类型。

其他注意点,搞清index从0开始,搞清逻辑上的第几个和数组显示使用的第几个的index的区别。

附上代码:public static double findMedianSortedArrays2(int[] nums1, int[] nums2){

if(nums1.length>nums2.length)//保证num1长度小,如果不小我交换一下

{

int team[]=nums2.clone();

nums2=nums1;

nums1=team;

}

int k=(nums1.length+nums2.length+1)/2;//理论中位数满足的位置

int left=0,right=nums1.length;//二分查找短的

while (left

int m1=(left+right)/2;//在短的位置

int m2=k-m1;//在长的第几个

//System.out.println(m1+" "+m2);

if(nums1[m1]

left=m1+1;

else {//right左移

right=m1;

}

}

//System.out.println(left+" "+k);

//左侧最大和右侧最小那个先算出来再说,根据奇偶再使用

double leftbig= Math.max(left==0?Integer.MIN_VALUE:nums1[left-1], k-left==0?Integer.MIN_VALUE:nums2[k-left-1]);

double rightsmall=Math.min(left==nums1.length?Integer.MAX_VALUE:nums1[left],k-left==nums2.length?Integer.MAX_VALUE:nums2[k-left]);

//System.out.println(rightsmall);

if((nums1.length+nums2.length)%2==0)

{

return (leftbig+rightsmall)/2;

}

else {

return leftbig;

}

}

结语

本次打卡结束,再接再励。

至于其他方法暂时先不学了,感觉这题还是挺有难度的,需要搞明白要点时候。

二分法分页 mysql_LeetCode 04寻找两个正序数组的中位数(困难)二分法相关推荐

  1. LeetCode 04寻找两个正序数组的中位数(困难)二分法

    题目描述: 呕心沥血的一个题解,点赞关注收藏,一键三联,一起加入我们打卡! 题目描述: 给定两个大小为 m 和 n 的正序(从小到大)数组 nums1 和 nums2. 请你找出这两个正序数组的中位数 ...

  2. LeetCode 4 寻找两个正序数组的中位数

    https://leetcode-cn.com/problems/median-of-two-sorted-arra 解决方案 Go 版本 func findMedianSortedArrays(nu ...

  3. 【LeetCode】4.寻找两个正序数组的中位数

    4.寻找两个正序数组的中位数 一.问题描述 给定两个大小分别为 m 和 n 的正序(从小到大)数组 nums1 和 nums2.请你找出并返回这两个正序数组的 中位数 . 二.问题简化 所谓中位数,就 ...

  4. 【LeetCode】【HOT】4. 寻找两个正序数组的中位数(二分查找)

    [LeetCode][HOT]4. 寻找两个正序数组的中位数 文章目录 [LeetCode][HOT]4. 寻找两个正序数组的中位数 package hot;public class Solution ...

  5. [二分搜索|快速选择] leetcode 4 寻找两个正序数组的中位数

    [二分搜索|快速选择] leetcode 4 寻找两个正序数组的中位数 1.题目 题目链接 给定两个大小为 m 和 n 的正序(从小到大)数组 nums1 和 nums2.请你找出并返回这两个正序数组 ...

  6. 2022-6-13 全O(1)的数据结构,两数相加,无重复字符的最长子串,寻找两个正序数组的中位数,盛最多水的容器,......

    1. 全 O(1) 的数据结构 Design a data structure to store the strings' count with the ability to return the s ...

  7. 寻找两个正序数组的中位数

    寻找两个正序数组的中位数 时隔许久,我又回来了. 题目:给定两个大小分别为m和n的正序(从小到大)数组nums1和nums2.请你找出并返回这两个正序数组的中位数. 要求算法的时间复杂度为O(log( ...

  8. 寻找两个正序数组的中位数Python解法

    给定两个大小分别为 m 和 n 的正序(从小到大)数组 nums1 和 nums2.请你找出并返回这两个正序数组的 中位数 . 算法的时间复杂度应该为 O(log (m+n)) . 例: 输入:num ...

  9. 算法:寻找两个正序数组的中位数。

    给定两个大小为 m 和 n 的正序(从小到大)数组 nums1 和 nums2. 请你找出这两个正序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n)). 你可以假设 nums1 和  ...

最新文章

  1. 对使用Jolt调用Tuxedo的一个简单的封装
  2. element-ui 表格table,动态显示每一列的,重置全选
  3. MATLAB imshow之后在四周加上边框
  4. HDSF主要节点解说(二)工作原理
  5. 接口规范 8. 播出认证相关接口
  6. c# 鼠标控制图片大小
  7. 建议0 不要让main函数返回void
  8. oc基础-OC基础-类的使用
  9. 公交车座位的坐垫设计成可替换,冬夏两用
  10. eval('{kkk:{}}')出错,eval('{}')与eval('var ss = {kkk:{}}')正常
  11. 求1+2阶乘+3阶乘+ 省略 +20阶乘的和
  12. m3 pcb开孔 螺丝_螺丝过孔及工艺孔尺寸参照表
  13. 沙盘模拟软件_我院学生参加第十六届全国大学生“新道杯”沙盘模拟经营大赛喜获佳绩...
  14. 统计学(贾俊平《第七版》)知识总结
  15. 接触式IC卡和非接触式IC卡有什么区别?
  16. 删除右键新建多余菜单
  17. 微信支付V3版本的 签名生成,验签,解密,统一下单的简单封装
  18. 如何将Blender模型导入Panda3d
  19. Macbook磁盘空间不足怎么办?
  20. 计算机系职业梦想演讲,我的职业梦想演讲稿

热门文章

  1. SpringCloud 01_单体应用到分布式系统演变过程
  2. leetcode 617. Merge Two Binary Trees | 617. 合并二叉树(Java)
  3. 【EasyUI】DataGrid 合并单元格 - 使用实例
  4. cxf环境搭建与第一个项目
  5. Linux gdb多进程、多线程调试
  6. CSS3的弹性盒子flex详解(1)
  7. jQuery的DOM操作之选择元素
  8. 【已解决】FileNotFoundError: [Errno 2] No such file or directory:_Python系列学习笔记
  9. 22行代码AC,三种解法——例题3-6_环状序列(UVa-1584)
  10. n阶自相关matlab代码,随机信号及其自相关函数和功率谱密度的MATLAB实现.doc