LeetCode-4-Median of Two Sorted Arrays(寻找两个有序数组的中位数)

题目

给定两个大小为 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

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

解答

这道题使用的是官方给出的解答,先看一些前瞻:
LeetCode-4-Median of Two Sorted Arrays(寻找两个有序数组的中位数)_第1张图片所以,这道题的要求是把两个数组 A, B 组合在一起并划分为两个半区Left 和 Right,这两个半区满足要求:

  1. Left.length = Right.length
  2. MaxLeft < MinRight

实现代码:(代码参照官方答案,加上自己理解的注释)

class Solution {
    public double findMedianSortedArrays(int[] nums1, int[] nums2) {
        int len1 = nums1.length;
        int len2 = nums2.length;
        
        if (len1 > len2) {	//确保短的数组在前面
			int[] temp = nums1;
			nums1 = nums2;
			nums2 = temp;
			
			len1 = nums1.length;
			len2 = nums2.length;
		}
        
        int iMin = 0;
        int iMax = len1;
        int halfLen = (len1 + len2 + 1) / 2;
        
        while(iMax >= iMin) {
        	int i = (iMax + iMin) / 2;
        	int j = halfLen - i;
        	
        	if (i < iMax && nums2[j-1] > nums1[i]) {	//确定nums1[i]没有越界
				//此时的i太小,需要右移
        		iMin = i + 1;
			}
        	
        	else if (i > iMin && nums1[i-1] > nums2[j] ) {
				//此时的i太大了,需要左移
        		iMax = i - 1;
			}
        	
        	else {
				//此时的i正好合适,处理特殊情况
        		int maxLeft = 0;
        		if (i == 0) {	//第一个数组元素全在右半区
					maxLeft = nums2[j-1];
					
				}else if (j == 0) {	//第一个数组元素全在左半区
					maxLeft = nums1[i-1];
				}
				else {
					maxLeft = Math.max(nums1[i-1], nums2[j-1]);
				}
        		if((len1 + len2) % 2 == 1) {
					//两数组总长度为奇数,中位数极为中间数
        			return maxLeft;
				}
        		
        		//两数组总长度为偶数,中位数为右半区最大和左半区最小的平均
        		int minRight = 0;
        		if (i == len1) {
					minRight = nums2[j];
				}else if (j == len2) {
					minRight = nums1[i];
				}else {
					minRight = Math.min(nums1[i], nums2[j]);
				}
        		
        		return (minRight + maxLeft) / 2.0;
        		
			}
        	
        }
        
        return 0.0;
    }
}

结果

运行结果

扩展

这道题难就难在数组的大小是不规定的,如果加上两个数组的长度一致这一条件,求中位数。会简单很多:

	//长度一致的两个数组查找中位数,思想是一样的
	public static double findMedian(int[] nums1, int[] nums2) {
		
		while(nums1.length != 1) {
			int l = nums1.length;						//两个数组的长度是一致的
			boolean mark = l % 2 == 0 ? true : false;	//判断l的奇偶性
			int index = mark ? l / 2 -1 : l / 2;
			double med1 = mark ? (nums1[index] + nums1[index + 1]) / 2.0 : nums1[index];
			double med2 = mark ? (nums2[index] + nums2[index + 1]) / 2.0 : nums2[index];
			
			int[] temp1 = new int[index + 1];
			int[] temp2 = new int[index + 1];
			if (med1 < med2) {
				//大的删去后面的,小的删去前面的
				System.arraycopy(nums1, mark ? index + 1 : index, temp1, 0, index + 1);
				System.arraycopy(nums2, 0, temp2, 0, index + 1);
				
			}else {
				System.arraycopy(nums2, mark ? index + 1 : index, temp2, 0, index + 1);
				System.arraycopy(nums1, 0, temp1, 0, index + 1);
			}
			
			nums1 = temp1;
			nums2 = temp2;
		}
		
		return (nums1[0] + nums2[0]) / 2.0;
	}

你可能感兴趣的:(Leetcode)