求解两个有序数组的中位数(要求时间复杂度为log(m + n))

1. 问题描述:题目来源于LeetCode网站

给定两个大小为 m 和 n 的有序数组 nums1 和 nums2 

请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n))

你可以假设 nums1 和 nums2 不会同时为空

2. 思路分析:

① 假如只是求解两个有序序列的中位数的话那么还是比较简单的,可以直接通过下表求解出中位数或者可以直接遍历两个有序序列找到中间的一个数字或者是两个数字,假如两个数组的总长度是奇数的话那么最中间的那个数字便是中位数,假如长度为偶数的时候那么需要求解出中间的两个数字,它们的平均数就是中位数

② 但是题目规定了时间复杂度为O(log(m + n))那么就不能够直接对两个数组进行遍历或者是使用的其他的方法来进行求解,对于时间复杂度以2为对数的情况那么我们可以这样想,肯定在遍历的时候以指数的方式来缩小数据规模的

③ 所以我们可以想到使用下面的方法来进行解决,因为我们是要求解出总长度中的第k个数字,所以分别在这两个序列中求解出第 k / 2个数字(每一次将数组中差不多一半的元素舍弃掉),在这两个数组中对应的这两个位置的数字,判断它们的大小关系,假如判断出第一个数组的位置的数字小于第二个数组位置的数字那么表明第一个数组从开始位置到当前位置的数字都不是中位数,所以就可以舍弃掉这些数字了,从该数组的下一个位置开始一般来说一次判断就可以缩小一个数组长度的一半,那么这个时候我们寻找的第k个数字那么就变成了寻找第 k 减去舍弃掉的长度的位置上的数字,最后k会变成1这样时候可以在方法中判断这两个序列的最小的那个就是中位数了

④ 需要注意两个数组求解第k个数字的时候有可能数组会越界所以需要进行简单的判断:

int i = start1 + Math.min(len1, k / 2) - 1;
int j = start2 + Math.min(len2, k / 2) - 1;
public class Main {
		public static void main(String[] args) {
			int num1[] = {1, 2, 3, 4, 5, 6, 7};
			int num2[] = {1, 2, 3, 4, 5, 6, 7};
			double res = findMedianSortedArrays(num1, num2);
			System.out.println(res);
		}
	
		public static double findMedianSortedArrays(int[] nums1, int[] nums2) {
		    int n = nums1.length;
		    int m = nums2.length;
		    int left = (n + m + 1) / 2;
		    int right = (n + m + 2) / 2;
		    //一个小技巧:将偶数和奇数的情况合并,如果是奇数,会求两次同样的 k 。
		    return (getKth(nums1, 0, n - 1, nums2, 0, m - 1, left) + getKth(nums1, 0, n - 1, nums2, 0, m - 1, right)) * 0.5;  
		}

	    private static int getKth(int[] nums1, int start1, int end1, int[] nums2, int start2, int end2, int k) {
	    	int len1 = end1 - start1 + 1;
	        int len2 = end2 - start2 + 1;
	        //让 len1 的长度小于 len2,这样就能保证如果有数组空了,一定是 len1 
	        if (len1 > len2) return getKth(nums2, start2, end2, nums1, start1, end1, k);
	        if (len1 == 0) return nums2[start2 + k - 1];
	        if (k == 1) return Math.min(nums1[start1], nums2[start2]);

	        int i = start1 + Math.min(len1, k / 2) - 1;
	        int j = start2 + Math.min(len2, k / 2) - 1;

	        if (nums1[i] > nums2[j]) {
	            return getKth(nums1, start1, end1, nums2, j + 1, end2, k - (j - start2 + 1));
	        }
	        else {
	            return getKth(nums1, i + 1, end1, nums2, start2, end2, k - (i - start1 + 1));
	        }
	    }
}

发布了498 篇原创文章 · 获赞 133 · 访问量 50万+

猜你喜欢

转载自blog.csdn.net/qq_39445165/article/details/100539124