[力扣c语言实现]4. 寻找两个有序数组的中位数

原题目连接

1. 题目描述

给定两个大小为 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.代码如下

初步思路:先排序后求中位数
double findMedianSortedArrays(int* nums1, int nums1Size, int* nums2, int nums2Size) {
    
    int i,j;
    int n = nums1Size + nums2Size;
    int temp;
    int tempn;
    
    int *num3 = (int*)malloc(sizeof(int)*n);//给数组分配内存
    memset(num3,0,sizeof(num3));
    
    //先排序,将两者合并成一个有序数组
    for (i=0;i < nums1Size;i++)//注意边界条件
    {
        *(num3+i) = *(nums1+i);
    }
    for(j=0;j < nums2Size;j++)//注意边界条件
    {
        *(num3+j+nums1Size) = *(nums2+j);
    }
    
    //合并好后排序,采用冒泡排序法进行排序
    for(j = 0 ;j < n ;j ++)
    {
        for(i = j+1 ; i < n ;i++)//一定要注意边界条件
        {
            temp = *(num3+j);
            tempn = *(num3+i);
            if(temp > tempn)//交换两者的值
            {
                *(num3+j) = tempn;
                *(num3+i) = temp;
            }
        }
    }
    
    //冒泡排序的思想就是:
    /* 将每一轮遍历的第一个元素与第二个元素开始直到最后的元素相比较,
       大于则交换,然后继续比较,要搞清楚的是,换值不换序,我是依据按序来取值比较,
       即使我比较的过程中会交换不同序号上的值,但是我的序号是没有变的
    */
    int up = n/2;
    int test = n%2;
    double num = 0;
    if(test==0)//偶数
    {
        int down  = up -1;
        num = num3[up]+num3[down];
        num = num/2;
        free(num3);
        return num;
    }
    else//奇数
    {
        num = num3[up];
        free(num3);
        return num;
    }
   return 0;
}
//本题目用的是冒泡排序,时间复杂度为T(n^2),空间复杂度为O(m+n);
//提交居然通过了??

优化时空复杂度

思路

首先,求一个长度为N的增序数组nums的中位数,
若N为偶数,则中位数为 (nums[(N/2)-1] + nums[N/2]) / 2,需要计算两个位置(N/2)- 1 ,N/2 处的数
若N为奇数,则中位数为 nums[N/2],只需要计算位置N/2处的数
其次,题目给我们的是两个增序数组,长度为n,m,而且还要求算法时空复杂度为O(n+m),也就是每个数组只能被遍历一次。
那么就直接联想到合并两个增序链表的处理方法,只不过在遍历的过程中,通过计数器判断是否在"合并"过程中得到了我们所要的位置的数即可。

解题方法

通过"合并"两个增序数组的过程,取处我们要的中位数的

复杂度

时间复杂度: O(n+m)

空间复杂度:

添加空间复杂度, 示例: O(1)O(1)
O(1)

/*
 *  date    2024-06-12
 *  author  zhangyb
 *  city    hangzhou 
 */

#include <iostream>
#include <vector>

using namespace std;

class Solution {
public:
    double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
        int allCnt = (int)nums1.size() + (int)nums2.size();
        //判断我们要从合并后的数组的何处开始取中位数
        int idx = allCnt / 2;
        int neededNums = 0;

        //通过两数组的长度判断我们要取出几个数来计算中位数
        if (allCnt % 2 == 1) {
            neededNums = 1;
        }
        else {
            idx -= 1;//如果合并后是偶数长度,则应该取: (N/2)- 1 ,N/2 这两个位置的中位数
            neededNums = 2;
        }

        int l1 = 0;
        int r1 = nums1.size() - 1;

        int l2 = 0;
        int r2 = nums2.size() - 1;

        int cnt = 0;
        int sum = 0;
        int size = neededNums;
        
        //进行"合并",我们并不需要真合并,只需要计数器判断处当前顺序是否是我们要的数
        while (l1 <= r1 && l2 <= r2) {
            if (nums1[l1] <= nums2[l2]) {
                if (cnt >= idx && size) {//cnt是计数器,idx是要取的数的起始位置,size则是需要取的数的个数
                    sum += nums1[l1];
                    size -= 1;
                }
                l1++;
            }
            else {
                if (cnt >= idx && size) {
                    sum += nums2[l2];
                    size -= 1;
                }
                l2++;
            }
            cnt++;
        }

        if (size == 0) {
            return (double)sum / neededNums;
        }
        
        while (l1 <= r1) {
            if (cnt >= idx && size) {
                sum += nums1[l1];
                size -= 1;
            }
            l1++;
            cnt++;
            if (size == 0) {
                return (double)sum / neededNums;
            }
        }

        while (l2 <= r2) {
            if (cnt >= idx && size) {
                sum += nums2[l2];
                size -= 1;
            }
            l2++;
            cnt++;
            if (size == 0) {
                return (double)sum / neededNums;
            }
        }
        return 0;
    }
};

int main () {
    std::vector<int> nums1 = {1, 3, 5, 7, 9};
    std::vector<int> nums2 = {2, 4, 6, 8, 10};

    Solution slu;
    std::cout << slu.findMedianSortedArrays(nums1, nums2) << "\n";
    
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值