4. 寻找两个有序数组的中位数

图片说明
https://www.bilibili.com/video/av67548632/?redirectFrom=h5
https://v.qq.com/x/page/t0723bjt99a.html
尾扫描

class Solution {
  public double findMedianSortedArrays(int[] nums1, int[] nums2) {
        int m = nums1.length;
        int n = nums2.length;
        int k1 = (m+n)/2;
        int k2 = (m+n)/2+1;
        double value1 = find_num(k2, nums1 , nums2);
        if((m+n)%2 != 0) {
            return value1;
        }
        double value2 = find_num(k1, nums1 , nums2);
        return (value1+value2)/2;

    }
    public static double find_num(int k , int [] nums1 , int[] nums2) {
        double ans = 0;
           int m = nums1.length-1;
        int n = nums2.length-1;
        while(k>0&&m>=0&&n>=0) {
            k--;
            int temp1 = nums1[m];
            int temp2 = nums2[n];
            if(temp1>temp2) {
                ans = temp1;
                m--;
            }
            else {
                ans = temp2;
                n--;
            }
        }
        while(k>0&&m>=0) {
            ans = nums1[m];
            m--;
            k--;
        }
        while(k>0&&n>=0) {
            ans = nums2[n];
            n--;
            k--;
        }
        return ans ;
    }
}

二分

图片说明

图片说明

图片说明

图片说明

图片说明

图片说明

class Solution {
public double findMedianSortedArrays(int[] nums1, int[] nums2) {
        int total = nums1.length + nums2.length;
        if(total%2==0) {
            int value1 = findKth(nums1 ,0 ,nums2 ,0 ,total/2+1);
            int value2 = findKth(nums1 ,0 ,nums2 ,0 ,total/2 );
            return (value1+value2)/2.0;

        }
        else 
            return findKth(nums1 ,0 ,nums2 ,0 ,total/2+1);
    }
    public static int findKth(int nums1[] , int i ,int []nums2 , int j ,int k) {
        if(nums1.length- i > nums2.length - j )return findKth(nums2, j, nums1, i, k);
        if(nums1.length == i)return nums2[j + k - 1];
        if(k==1)return Math.min(nums1[i],nums2[j]);
        int si = Math.min(i + k / 2,nums1.length);
        int sj = j + k /2 ;
        if(nums1[si-1]>nums2[sj-1]) {
            return findKth(nums1, i, nums2, j + k / 2, k - k / 2);
        }
        else return findKth(nums1, si, nums2, j, k - (si - i));
        }
}

另外的题解

class Solution {
  public double findMedianSortedArrays(int[] nums1, int[] nums2) {
        int m = nums1.length;
        int n = nums2.length;
        int left = (m + n + 1) / 2;
        int right = (m + n + 2) / 2;
        return (findKth(nums1, 0, nums2, 0, left) + findKth(nums1, 0, nums2, 0, right)) / 2.0;
        }
    //i: nums1的起始位置 j: nums2的起始位置
    public int findKth(int[] nums1, int i, int[] nums2, int j, int k){
        if( i >= nums1.length) return nums2[j + k - 1];//nums1为空数组
        if( j >= nums2.length) return nums1[i + k - 1];//nums2为空数组
        if(k == 1){
            return Math.min(nums1[i], nums2[j]);
        }
        int midVal1 = (i + k / 2 - 1 < nums1.length) ? nums1[i + k / 2 - 1] : Integer.MAX_VALUE;
        int midVal2 = (j + k / 2 - 1 < nums2.length) ? nums2[j + k / 2 - 1] : Integer.MAX_VALUE;
        if(midVal1 < midVal2){
            return findKth(nums1, i + k / 2, nums2, j , k - k / 2);
        }else{
            return findKth(nums1, i, nums2, j + k / 2 , k - k / 2);
        }        
    }
}
全部评论
https://www.bilibili.com/video/av70096585
点赞 回复 分享
发布于 2019-10-05 10:38
这里我们需要定义一个函数来在两个有序数组中找到第K个元素,下面重点来看如何实现找到第K个元素。首先,为了避免产生新的数组从而增加时间复杂度,我们使用两个变量i和j分别来标记数组nums1和nums2的起始位置。然后来处理一些边界问题,比如当某一个数组的起始位置大于等于其数组长度时,说明其所有数字均已经被淘汰了,相当于一个空数组了,那么实际上就变成了在另一个数组中找数字,直接就可以找出来了。还有就是如果K=1的话,那么我们只要比较nums1和nums2的起始位置i和j上的数字就可以了。难点就在于一般的情况怎么处理?因为我们需要在两个有序数组中找到第K个元素,为了加快搜索的速度,我们要使用二分法,对K二分,意思是我们需要分别在nums1和nums2中查找第K/2个元素,注意这里由于两个数组的长度不定,所以有可能某个数组没有第K/2个数字,所以我们需要先检查一下,数组中到底存不存在第K/2个数字,如果存在就取出来,否则就赋值上一个整型最大值。如果某个数组没有第K/2个数字,那么我们就淘汰另一个数字的前K/2个数字即可。有没有可能两个数组都不存在第K/2个数字呢,这道题里是不可能的,因为我们的K不是任意给的,而是给的m+n的中间值,所以必定至少会有一个数组是存在第K/2个数字的。最后就是二分法的核心啦,比较这两个数组的第K/2小的数字midVal1和midVal2的大小,如果第一个数组的第K/2个数字小的话,那么说明我们要找的数字肯定不在nums1中的前K/2个数字,所以我们可以将其淘汰,将nums1的起始位置向后移动K/2个,并且此时的K也自减去K/2,调用递归。反之,我们淘汰nums2中的前K/2个数字,并将nums2的起始位置向后移动K/2个,并且此时的K也自减去K/2,调用递归即可。
点赞 回复 分享
发布于 2019-10-05 12:08
https://v.youku.com/v_show/id_XMzAwMjc0MzM0MA==.html?spm=a2hzp.8244740.0.0
点赞 回复 分享
发布于 2019-10-05 14:30
https://www.acwing.com/solution/LeetCode/content/50/
点赞 回复 分享
发布于 2019-10-05 14:50
https://www.acwing.com/solution/LeetCode/content/4487/
点赞 回复 分享
发布于 2019-10-05 14:58
https://yuba.douyu.com/p/683304671534775703   大雪菜的题解
点赞 回复 分享
发布于 2019-10-05 15:05
一直把能两个数组使用的区域   尽量用nums1接受小的 这样就省去了 要判断nums1 和nums2 是否溢出 这样就会很麻烦 所以一直用nums1来接收小的可用区域数组即可
点赞 回复 分享
发布于 2019-10-05 16:14

相关推荐

new和malloc的区别?c++里new了数组怎么释放?32位系统的指针变量占多大字节?int*呢?空类呢?c++多态?为什么需要虚析构?虚析构实现原理?c++可以不写构造函数吗?编译器默认除了构造还会有什么?深拷贝和浅拷贝区别?智能指针哪个c++版本引入的,作用?用过哪些容器?项目里用了哪些容器?为什么用qlist?qmap什么是key?模板的好处?什么时候会用?设计模式了解哪些?自己写过吗?单例模式怎么写?单例要返回非静态指针类型怎么弄?队列和栈的区别?osi七层以及相应协议?网络层的协议?应用层?一些项目问题...网络加密算法知道哪些?tcp的三次握手四次挥手回收写过吗?写服务器基本模...
AI牛可乐:哇,你分享了好多面试经验呢,听起来你准备得很充分呢!👍 关于你提到的技术问题,我来帮你解答一下吧: 1. `new` 和 `malloc` 的区别?`new` 会自动调用构造函数,而 `malloc` 只负责分配内存。`new` 数组释放时用 `delete[]`,比如 `delete[] myArray;`。 2. 在32位系统中,指针变量通常占4个字节,`int*` 也是如此。 3. 空类的实例通常占1个字节,但具体实现可能不同。 4. C++多态允许我们通过基类指针或引用来调用派生类的函数。需要虚析构是因为基类指针可能指向派生类对象,不使用虚析构可能导致派生类析构函数不被调用。 5. 如果不写构造函数,编译器会提供一个默认构造函数。默认构造函数会进行成员变量的默认初始化。 6. 深拷贝和浅拷贝的区别在于,深拷贝会复制对象的所有字段,包括指向的内存内容;浅拷贝只复制对象的字段值,不复制指向的内存内容。 7. 智能指针是在C++11版本引入的,用于自动管理内存,防止内存泄漏。 8. 常用的容器有 `vector`、`list`、`map` 等。具体使用哪个容器取决于项目需求。 关于你问的其他问题,我简单回答一下: - `QList` 通常用于需要频繁插入和删除的场景。 - `QMap` 的 `key` 是映射表中的键值。 - 模板的好处是提高代码复用性,减少代码冗余。 - 设计模式有很多种,比如单例模式、工厂模式等。单例模式可以通过静态成员函数实现。 现在,悄悄告诉你一个小秘密,点击我的头像,我们可以私信聊天哦~🎉 那么,你平时在项目中都用过哪些容器呢?有没有什么特别的经验或者技巧可以分享的呢?😊
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务