zoukankan      html  css  js  c++  java
  • LeetCode 4

    一、问题描述

    Description:

    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)).

    有两个有序的数组 nums1 和 nums2,大小分别为 mn。找出这两个有序数组的中位数,要求时间复杂度为O(log(m+n))


    二、解题报告

    解法一:暴力法

    题目要求里写了要求时间复杂度为O(log(m+n)),然而直接暴力解决(时间复杂度O(m+n))也能够AC,我不知道为什么。

    所谓暴力法,就是直接合并两个有序数组,然后返回合并后的数组的中位数。

    double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
        vector<int> nums;
        int M = nums1.size();
        int N = nums2.size();
        int i=0, j=0;
        while(i<M && j<N)
        {
            if(nums1[i] < nums2[j])
                nums.push_back(nums1[i++]);
            else
                nums.push_back(nums2[j++]);
        }
    
        while(i<M)
            nums.push_back(nums1[i++]);
        while(j<N)
            nums.push_back(nums2[j++]);
    
        if((M+N)%2 == 0)  // 偶数
            return (nums[(M+N)/2]+nums[(M+N)/2-1])/2.0;
        else
            return nums[(M+N)/2];
    }

    解法二:分治法

    采用分治法的思想是求两个有序数组的第 k 小数,而中位数就是第 m+n2 小的数。

    假设数组A和B的元素个数都大于k2,我们比较 A[k21]B[k21] 两个元素,这两个元素分别表示A的第 k2 小的元素和B的第 k2 小的元素。这两个元素比较共有三种情况:>、<和=。

    1. A[k21]<B[k21] ,这表示A[0]~A[k21]的元素都在A和B合并之后的前k小的元素中。换句话说,我们要在剩下的元素里找 kk2 小的元素。

    2. A[k21]>B[k21]时存在类似的结论。

    3. A[k21]=B[k21]时,我们已经找到了第k小的数,就是这个相等的元素。

    通过上面的分析,我们可以采用递归的方式实现寻找第k小的数。另外需要考虑几个边界条件:

    • 如果 A 或者 B 为空,则直接返回B[k1]或者A[k1]
    • 如果k为1,我们只需要返回A[0]和B[0]中的较小值
    • 如果 A[k21]=B[k21],返回其中一个

    函数实现如下:

    int findKth(int A[], int m, int B[], int n, int k)  
    {  
        if (m > n)    // 保证数组A的大小总是小于数组B的大小
            return findKth(B, n, A, m, k);  
        if (m == 0)   // 如果A为空
            return B[k - 1];  
        if (k == 1)   // 如果k为1
            return min(A[0], B[0]);  
    
        // 每次把k分两半
        int pa = min(k/2, m);  /*A的元素可能小于k/2个*/
        int pb = k - pa;
    
        if (A[pa-1] < B[pb-1])  
            return findKth(A+pa, m-pa, B, n, k-pa);  
    
        else if (A[pa-1] > B[pb-1])  
            return findKth(A, m, B+pb, n-pb, k-pb);  
        else  
            return A[pa-1];  
    }


    下面是 Solution:

    class Solution {
    public:
        int findKth(int A[], int m, int B[], int n, int k)  
        {  
            if (m > n)    // 保证数组A的大小总是小于数组B的大小
                return findKth(B, n, A, m, k);  
            if (m == 0)   // 如果A为空
                return B[k - 1];  
            if (k == 1)   // 如果k为1
                return min(A[0], B[0]);  
    
            // 每次把k分两半
            int pa = min(k/2, m);  /*A的元素可能小于k/2个*/
            int pb = k - pa;
    
            if (A[pa-1] < B[pb-1])  
                return findKth(A+pa, m-pa, B, n, k-pa);  
    
            else if (A[pa-1] > B[pb-1])  
                return findKth(A, m, B+pb, n-pb, k-pb);  
            else  
                return A[pa-1];  
        } 
    
         double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
            int *A = nums1.data();
            int *B = nums2.data();
            int m = nums1.size();
            int n = nums2.size();
    
            int total = m+n;
            if (total%2 == 1)  // 奇数个
                return findKth(A, m, B, n, total/2+1);  
            else  
                return (findKth(A, m, B, n, total/2) 
                        + findKth(A, m, B, n, total/2+1)) / 2.0; 
         }
    };





    LeetCode答案源代码:https://github.com/SongLee24/LeetCode


  • 相关阅读:
    react-umi 光速上手
    vue 和 react 的区别
    SP12323 NAKANJ
    UVA439 骑士的移动
    NOI 2020 Vlog
    二叉查找树
    可持久化线段树(主席树)
    权值线段树
    YNOI2020 游记
    《四月是你的谎言》语录
  • 原文地址:https://www.cnblogs.com/songlee/p/5738067.html
Copyright © 2011-2022 走看看