力扣 寻找两个正序数组的中位数 C++

题目:给定两个大小分别为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。请你找出并返回这两个正序数组的 中位数 。

题目说明:

输入:nums1 = [1,3], nums2 = [2]

输出:2.00000

解释:合并数组 = [1,2,3] ,中位数 2

关于这个题目我先给出自己的解法,因为现在我自己的段位不高很难想到什么高效的算法来解决这道题但是自己的解法也能解决这道题,只不过自己的解法比较暴力所以耗时也比较浪费空间,我也不甘堕落学习了别人高效的代码在下面也会给大家分享我对别人高效代码的理解。

自己的解法思路:首先先将两个数组中的一个数组(我们这里就选择nums2)中的值一次赋值到一个动态数组中(该动态数组是我们在堆区申请的一块内存内存的大小要和两个数组总长度一样长,因为该动态数组是由nums2赋值得到的所以现有的长度nums2一样长),接下来就要将nums1中的值依次和动态数组中的值进行比较然后插入到动态数组中(元素插入到动态数组中会存在数组中的元素移动,从插入位置截止让最后一个元素开始向后移动一个位置),这样就可以的到一个完整的有序的数组。如果nums2的长度为0就直接找出nums1中的中位数并将其返回,如果nums1的长度为0就直接找出nums2中的中位数,代码中还有很多的细节请自己阅读代码大致的思路已经说明白。

代码:

float project(vector<int>& nums1, vector<int>& nums2) {
	int* p = new int[nums1.size() + nums2.size()+2];
	memset(p, 0, sizeof(int) * (nums1.size() + nums2.size() + 2));
	for (auto i = 0;i < nums2.size();i++) {
		p[i] = nums2[i];
	}
	int c = nums2.size();
	for (auto i = 0;i < nums1.size();i++) {
		for (auto j = 0;j < c;j++) {
			if (nums1[i] < p[j]) {
				for (int e = c-1;e >= j;e--) {
					int b = p[e];
					    p[e+1] = b;
					if (e == j) {
						p[j] = nums1[i];
						c++;
						break;
					}
				}
			}else 
			if (nums1[i] >= p[c-1]) {
				p[c] = nums1[i];
				c++;
				break;
			}
			else {
				continue;
			}
			break;
		}
	}
	if (c == 0) {
		if (nums1.size() % 2 == 0) {
			int q = nums1.size() / 2;
			return (nums1[q] + nums1[q - 1]) / 2.0;
		}
		else {
			int q = nums1.size() / 2;
			return nums1[q] * 1.0;
		}
	}
	if (c % 2 == 0) {
		int q = c / 2;
		return (p[q] + p[q - 1]) / 2.0;
	}
	else {
		int q = c / 2;
		return p[q]*1.0;
	}
}

接下来为大家分享别人的代码:

归并算法!

思路:在写这个题之前我没有学过归并算法要不解题就变得很简单了!现在就说一下归并算法,什么是归并算法呢?归并算法就是将两个数组合并为一个数组可以合并有序数组也可以和并无序数组但是合并出来的数组都是有序的,这个题不用合并无序数组因为所给的数组都是有序的。先定义一个数组该数组的长度和两个数组的总长度一样长这样就可以保存两个数组中的元素,因为两个数组是有序的这样归并起来也是一个有序的数组,那是怎么归并的呢?其实很简单先给出代码然后再进行讲解。

    double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
        int m = nums1.size(), n = nums2.size(), k = 0, i = 0, j = 0;
        vector<int> sub(m + n,0);//定义一个容器将容器长度设置为m+n,并将里面的元素的值都赋值为0
        while (i < m && j < n)
            sub[k++] = nums1[i] < nums2[j] ? nums1[i++] : nums2[j++];
        while (i < m) sub[k++] = nums1[i++];
        while (j < n) sub[k++] = nums2[j++];
        return k % 2 ? sub[k / 2] : (sub[k / 2] + sub[k / 2 - 1]) / 2.0; // 判断奇偶
    }

比较两个数组中的值从数组中的位置0开始比较如果nums1[0]<nums2[0]那么就先将nums1[0]保存在sub[0]的位置,再将nums2[0]与nums1[1]比较如果nums2[0]<nums1[1]就将nums2[0]保存在

sub[1]的位置,依次这样循环下去就可以将两个数组中的元素入保存在sub数组中。

那么这两段代码是用来干什么的呢?

  while (i < m) sub[k++] = nums1[i++];
  while (j < n) sub[k++] = nums2[j++];

这两段代码是用来处理极端情况和两个数组的长度不是一样长的时候根据我们的循环条件(  while (i < m && j < n))当有一个数组遍历完就会退出循环,如果nums1[1,2,3,4]而nums2[5,6,7,8,9]这样nums1中的值都保存在数组sub中以后nums2中的第一个值都还没有保存在sub中,这样就会遍历下面的两个循环,将剩余数组中的值都保存在sub数组中,这种算法是不是很高效也省内存。

再给大家分享一种算法:

双指针!

什么是双指针呢?现在就说以下双指针其实双指针就是一种思想现在就针对这道题说一下,在这个题中我们就定义两个整数用来遍历两个数组这两个整数就相当于两个指针,根据这两个整数在数组中的下标位置就可以索引到数组中的值。直接上代码进行讲解。

代码:

   double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
        // 定义 i j 2个指针分别指针2个数组
        int m = nums1.size(), n = nums2.size(), i = 0, j = 0, l = 0, r = 0;
        for (int x = 0; x <= (m + n) / 2; x++) {
            l = r;
            r = (i < m && (j >= n || nums1[i] < nums2[j])) ?
                nums1[i++] : nums2[j++];
        }
        return (m + n) & 1 ? r : (l + r) / 2.0;
    }

其实逻辑也很简单!只要上面归并算法实现的核心代码理解了现在双指针的实现就不难理解了,就是定义两个整数用做数组的下标用来索引数组中的值,还是从nums1[0]和nums2[0]依次进行比较哪个大就将那个值赋值给 r 而 l 是用来保存 r 前面的值,现在比较难理解的就是判断条件 (i < m && (j >= n || nums1[i] < nums2[j]) )当nums1没有遍历完的时候 i < m 这个判断条件一直都在执行,而(j >= n || nums1[i] < nums2[j])这个判断条件中j >= n 这个条件只有在nums2遍历完以后才执行,所以在nums1.nums2没有遍历完时一直都执行的是(i < m && nums[i] < nums[j])这个判断条件哪个数组中对应的值小就定位到哪个数组中的值并将该值赋值给 r ,当nums1遍历完直接j就遍历nums2,那么如果在nums1遍历完之前nums2就遍历完执行的判断条件是(i < m && j >= n)这样一直遍历的是nums1,直到循环执行到两个数组总长度的中间位置就可以退出循环就可以定位到中位数。

说实话这两种算法都很牛逼!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值