LeetCode(困难)寻找两个有序数组的中位数(c#)

题目为
给定两个大小为 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 + 3)/2 = 2.5。

我的第一个题解为直接对两个数组排序建立整个的数组,返回中间的值就可以了,但时间复杂度为不满足O(log(m + n)),但思路简单,代码如下

		public double FindMedianSortedArrays(int[] nums1, int[] nums2)
        {
            if (nums1==null)
            {
                if (nums2.Length % 2==0)
                {
                    return (nums2[nums2.Length / 2] + nums2[nums2.Length / 2 - 1]) / 2.000;
                }
                else
                {
                    return nums2[nums2.Length / 2];
                }
            }
            if (nums2 == null)
            {
                if (nums1.Length % 2 == 0)
                {
                    return (nums1[nums1.Length / 2] + nums1[nums1.Length / 2 - 1]) / 2.000;
                }
                else
                {
                    return nums1[nums1.Length / 2];
                }
            }
            int allLength= nums2.Length + nums1.Length;
            List<int> li = new List<int>();
            int left = 0;
            int right = 0;
            for (int i = 0; i < allLength; i++)
            {
                if (left>nums1.Length-1)
                {
                    li.Add(nums2[right]);
                    right++;
                    continue;
                }
                if (right > nums2.Length-1)
                {
                    li.Add(nums1[left]);
                    left++;
                    continue;
                }
                if (nums1[left]<=nums2[right])
                {
                    li.Add(nums1[left]);
                    left++;
                }
                else
                {
                    li.Add(nums2[right]);
                    right++;
                }
            }
            if (li.Count % 2 == 0)
            {
                return (li[li.Count / 2] + li[li.Count / 2 - 1]) / 2.000;
            }
            else
            {
                return li[li.Count / 2];
            }
        }

看了官方题解,二分法求解题解写的一头雾水,看了下面某位老哥的题解,才恍然大雾,附上老哥的题解思路
两个有序数组求中位数,问题一般化为,求两个有序数组的第k个数,当k = (m+n)/2时为原问题的解。
怎么求第k个数?分别求出第一个和第二个数组的第 k / 2个数 a 和 b,然后比较 a 和 b,当a < b ,说明第 k 个数位于 a数组的第 k / 2个数后半段,或者b数组的 第 k / 2 个数前半段,问题规模缩小了一半,然后递归处理就行。
时间复杂度是 O(log(m+n))

这位老哥的题解链接为题解链接

我根据题解写出的c#代码为

        public double FindMedianSortedArrays(int[] nums1, int[] nums2)
        {
            if (nums1 == null)
            {
                if (nums2.Length % 2 == 0)
                {
                    return (nums2[nums2.Length / 2] + nums2[nums2.Length / 2 - 1]) / 2.000;
                }
                else
                {
                    return nums2[nums2.Length / 2];
                }
            }
            if (nums2 == null)
            {
                if (nums1.Length % 2 == 0)
                {
                    return (nums1[nums1.Length / 2] + nums1[nums1.Length / 2 - 1]) / 2.000;
                }
                else
                {
                    return nums1[nums1.Length / 2];
                }
            }
            int total = nums1.Length + nums2.Length;
            if ((total & 1) == 1)
            {
                return GetNumMedian( 0, nums1,  0, nums2, total / 2 + 1);
            }
            return (GetNumMedian( 0, nums1,  0, nums2, total / 2) + GetNumMedian( 0, nums1,  0, nums2, total / 2 + 1)) / 2.0;
        }
        /// <summary>
        /// 递归求解方法
        /// </summary>
        /// <param name="begin1">第一个数组当前开始数</param>
        /// <param name="nums1">第一个数组</param>
        /// <param name="begin2">第二个数组当前开始数</param>
        /// <param name="nums2">第二个数组</param>
        /// <param name="k">两个数组中所要寻找的第K个数字</param>
        /// <returns></returns>
        public double GetNumMedian(int begin1,int[] nums1,int begin2,int[] nums2,int k)
        {
            //当两个数组中某个数组已经到达末尾了,则中位数在另一个数组的(begin位+第k位)
            if (begin1>=nums1.Length)
            {
                return nums2[begin2 + k - 1];
            }
            if (begin2 >= nums2.Length)
            {
                return nums1[begin1 + k - 1];
            }
            if (k==1)
            {
                return Math.Min(nums1[begin1], nums2[begin2]);
            }
            int aMax = int.MaxValue;
            int bMax = int.MaxValue;
            if (begin1 + k / 2 - 1 < nums1.Length)
                aMax = nums1[begin1 + k / 2 - 1];
            if (begin2 + k / 2 - 1 < nums2.Length)
                bMax = nums2[begin2 + k / 2 - 1];
            //如果a数组的第 k / 2 个数小于b数组的第 k / 2 个数,表示总的第 k 个数位于 a的第k / 2个数的后半段,或者是b的第 k / 2个数的前半段
            //由于范围缩小了 k / 2 个数,此时总的第 k 个数实际上等于新的范围内的第 k - k / 2个数,依次递归
            if (aMax < bMax)
                return GetNumMedian(begin1 + k / 2, nums1, begin2, nums2, k - k / 2);
            //否则相反
            return GetNumMedian(begin1, nums1,begin2 + k / 2, nums2, k - k / 2);
        }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值