leetcode刷题记录——寻找两个正序数组的中位数

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

算法的时间复杂度应该为 O(log (m+n)) 。

来源:力扣(LeetCode)链接:https://leetcode.cn/problems/median-of-two-sorted-arrays/

自己的思路:

将两个有序数组通过i,j双下标来进行遍历判断比较将小的插入到新建立的合并数组并创建k与较少的有序下标一起递增,直到下标与有序数组长度不相等时退出,将剩余没添加的有序数组再以同样的方式加到合并数组,(其实就是二分法)再通过两个有序数组的长度遍历合并数组判断中位数,注意返回类型用double转换。

C语言:

doublefindMedianSortedArrays(int*nums1, intnums1Size, int*nums2, intnums2Size){

//合并数组

inti=0;

intj=0;

intk=0;

intc[nums1Size+nums2Size];

intlen=0;

while (i!=nums1Size&&j!=nums2Size)

{

if (nums1[i] <nums2[j])

c[k++] =nums1[i++];

else

c[k++] =nums2[j++];

}

if (i==nums1Size)

{

while (j!=nums2Size)

c[k++] =nums2[j++];

}

else

{

while (i!=nums1Size)

c[k++] =nums1[i++];

}

//找中位数

doublemid=0;

len=nums1Size+nums2Size;

if (len%2!=0)

mid=c[len/2];

else

mid= (double)(c[len/2-1] +c[len/2]) /2;

returnmid;

}

// 时长:16ms 空间:6.4MB

Go语言:

根据学到的归并算法进行的排序处理

funcmergeSort(arr []int) []int {

length :=len(arr)

iflength<2 {

returnarr

}

middle :=length/2

left :=arr[0:middle]

right :=arr[middle:]

returnmerge(mergeSort(left), mergeSort(right))

}

funcmerge(left []int, right []int) []int {

varresult []int

forlen(left) !=0&&len(right) !=0 {

ifleft[0] <=right[0] {

result=append(result, left[0])

left=left[1:]

} else {

result=append(result, right[0])

right=right[1:]

}

}

forlen(left) !=0 {

result=append(result, left[0])

left=left[1:]

}

forlen(right) !=0 {

result=append(result, right[0])

right=right[1:]

}

returnresult

}

funcfindMedianSortedArrays(nums1 []int, nums2 []int) float64 {

varc []int

c=merge(nums1, nums2)

c=mergeSort(c)

varmidfloat64

iflen(c)%2!=0 {

mid=float64(c[len(c)/2])

} else {

mid=float64((c[len(c)/2-1] +c[len(c)/2])) /2

}

returnmid

}

// 时长:24ms 空间:6.8MB

佬的清晰思路:

这道题让我们求两个有序数组的中位数,而且限制了时间复杂度为O(log (m+n)),看到这个时间复杂度,自然而然的想到了应该使用二分查找法来求解。那么回顾一下中位数的定义,如果某个有序数组长度是奇数,那么其中位数就是最中间那个,如果是偶数,那么就是最中间两个数字的平均值。这里对于两个有序数组也是一样的,假设两个有序数组的长度分别为m和n,由于两个数组长度之和 m+n 的奇偶不确定,因此需要分情况来讨论,对于奇数的情况,直接找到最中间的数即可,偶数的话需要求最中间两个数的平均值。为了简化代码,不分情况讨论,我们使用一个小trick,我们分别找第 (m+n+1) / 2 个,和 (m+n+2) / 2 个,然后求其平均值即可,这对奇偶数均适用。加入 m+n 为奇数的话,那么其实 (m+n+1) / 2 和 (m+n+2) / 2 的值相等,相当于两个相同的数字相加再除以2,还是其本身。

这里我们需要定义一个函数来在两个有序数组中找到第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,调用递归即可。

作者:Wait想念链接:https://leetcode.cn/problems/median-of-two-sorted-arrays/comments/

总结:

这次题还是很不错,自己虽然能做出来但是感觉没有达到大佬们的清晰思路分析,说明自己还是非常欠缺不能掉以轻心,这题找到思路就剩是对语言的基础知识掌握能力问题,但是同样也能学倒不少东西非常不错,比如归并排序,明天继续加油冲冲冲!

收获:

C语言的浮点型及整型除法问题,Go语言中string、int、float相互转换,归并排序,Go语言和C语言初始化的差异。

学习链接:

Go语言中string、int、float相互转换:https://blog.csdn.net/HYZX_9987/article/details/100172848

C语言浮点型及整型除法:https://blog.csdn.net/weixin_49635198/article/details/116708682

十大经典排序——归并排序:https://www.runoob.com/w3cnote/merge-sort.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值