[LeetCode] 4. Median of Two Sorted Arrays

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

The median is 2.0

Example 2:

nums1 = [1, 2]
nums2 = [3, 4]

The median is (2 + 3)/2 = 2.5

思路

  • 暴力算法:逐一遍历元素,将两个数组合并成一个有序数组。
  • 复杂性分析:
    • 时间复杂度:O(n*m).【不符合题目要求】
    • 空间复杂度:O(1).

题解

class Solution {
public:
    double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
        vector<int> nums = nums1;
        for (int i=0; i < nums2.size(); i++) {
            bool found = 0;
            for (std::vector<int>::iterator it = nums.begin(); it != nums.end(); ++it) {
                if (nums2[i] < *it) {
                    nums.insert(it, nums2[i]);
                    found = 1;
                    break;
                }
            }
            if (!found) {
                nums.push_back(nums2[i]);
            }
        }

        double result = 0;
        int size = nums.size();
        if (size%2 == 0) {
            result = (double)(nums[size/2] + nums[size/2 - 1]) / 2;
        } else {
            result = nums[size/2];
        }

        return result;
    }
};

优化

思路

上述方法的时间主要消耗在排序上,但事实上我们只需要找到第k大的数,而且两个给定数组已经排好序,所以不需要全排序的操作,直接搜寻即可。可用类似二分查找的方法将时间复杂度降至O(log(m+n))

代码

class Solution {  
public:  
    double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {   
        int len1=nums1.size();  
        int len2=nums2.size();  
        int len=len1+len2;  
        if(len & 1) return findKth(nums1,0,nums2,0,len/2+1);
        return (findKth(nums1,0,nums2,0,len/2)+findKth(nums1,0,nums2,0,len/2+1))/2;  
    }  

    double findKth(vector<int>& nums1,int i1,vector<int>& nums2,int i2,int k){  
        if(i1>=nums1.size()) return nums2[i2+k-1];
        if(i2>=nums2.size()) return nums1[i1+k-1];
        if(k==1) return min(nums1[i1],nums2[i2]);

        int key1=i1+k/2-1>=nums1.size()?INT_MAX:nums1[i1+k/2-1];  
        int key2=i2+k/2-1>=nums2.size()?INT_MAX:nums2[i2+k/2-1];  
        if(key1<key2) return findKth(nums1,i1+k/2,nums2,i2,k-k/2);
        return findKth(nums1,i1,nums2,i2+k/2,k-k/2);
    }
};  

反思

  1. 查找思路
    对于一个长度为 n 的已排序数列 a,若 n 为奇数,中位数为 a[n / 2 + 1] , 若 n 为偶数,则中位数 (a[n/2] + a[n/2 + 1]) / 2。
    求两个数组的中位数,不妨设数列 A 元素个数为 n,数列 B 元素个数为 m,各自升序排序,则中位数则为第 (n+m)/2 小的数。因此,转化为在两个数列中求出第 K 小的元素便可以解决该问题。
    取 A[k / 2] B[k / 2] 比较,如果 A[k / 2] > B[k / 2] 那么,所求的元素必然不在 B 的前 k/2 个元素中(证明反证法);反之,必然不在 A 的前 k/2 个元素中,于是我们可以将 A 或 B 数列的前 k/2 元素删去,求剩下两个数列的 k - k/2小元素,于是得到了数据规模变小的同类问题,递归解决。
    如果 k/2 大于某数列的个数,所求元素必然不在另一数列的前 k/2 个元素中,同上操作即可。
  2. 转变思路,灵活运用。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
对于计算机专业的学生而言,参加各类比赛能够带来多方面的益处,具体包括但不限于以下几点: 技能提升: 参与比赛促使学生深入学习和掌握计算机领域的专业知识与技能,如编程语言、算法设计、软件工程、网络安全等。 比赛通常涉及实际问题的解决,有助于将理论知识应用于实践中,增强问题解决能力。 实践经验: 大多数比赛都要求参赛者设计并实现解决方案,这提供了宝贵的动手操作机会,有助于积累项目经验。 实践经验对于计算机专业的学生尤为重要,因为雇主往往更青睐有实际项目背景的候选人。 团队合作: 许多比赛鼓励团队协作,这有助于培养学生的团队精神、沟通技巧和领导能力。 团队合作还能促进学生之间的知识共享和思维碰撞,有助于形成更全面的解决方案。 职业发展: 获奖经历可以显著增强简历的吸引力,为求职或继续深造提供有力支持。 某些比赛可能直接与企业合作,提供实习、工作机会或奖学金,为学生的职业生涯打开更多门路。 网络拓展: 比赛是结识同行业人才的好机会,可以帮助学生建立行业联系,这对于未来的职业发展非常重要。 奖金与荣誉: 许多比赛提供奖金或奖品,这不仅能给予学生经济上的奖励,还能增强其成就感和自信心。 荣誉证书或奖状可以证明学生的成就,对个人品牌建设有积极作用。 创新与研究: 参加比赛可以激发学生的创新思维,推动科研项目的开展,有时甚至能促成学术论文的发表。 个人成长: 在准备和参加比赛的过程中,学生将面临压力与挑战,这有助于培养良好的心理素质和抗压能力。 自我挑战和克服困难的经历对个人成长有着深远的影响。 综上所述,参加计算机领域的比赛对于学生来说是一个全面发展的平台,不仅可以提升专业技能,还能增强团队协作、沟通、解决问题的能力,并为未来的职业生涯奠定坚实的基础。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值