4.尋找兩個有序數組的中位數

題目:

給定兩個大小爲 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

 

思路:

首先判斷兩個數組總長度爲奇數還是偶數,奇數則只需找最終的一個元素即可,偶數則需要尋找下標爲len/2和len/2-1的兩個元素。然後再就是找中間元素的步驟了,以總長度爲奇數爲例,在兩個數組合並的大數組中中位數的下標爲(len1+len2)/2,然後分別兩個數組從前向後比較,找到下標爲(len1+len2)/2的元素

代碼:

	public static double findMedianSortedArrays(int[] nums1, int[] nums2) {
		int point1 = 0, point2 = 0;
		double mid;
		if ((nums1.length + nums2.length) % 2 == 0) {
			int median1 = 0, median2 = 0;
			int medianIndex = (nums1.length + nums2.length) / 2;
			for (int i = 0; i <= medianIndex; i++) {
				median2 = median1;
				if (point1 >= nums1.length) {
					median1 = nums2[point2];
					point2++;
					continue;
				}
				if (point2 >= nums2.length) {
					median1 = nums1[point1];
					point1++;
					continue;
				}
				if (nums1[point1] < nums2[point2]) {
					median1 = nums1[point1];
					point1++;
				} else {
					median1 = nums2[point2];
					point2++;
				}
			}
			mid = (median1 + median2) / 2.0;
		} else {
			int median = 0;
			int medianIndex = (nums1.length + nums2.length) / 2;
			for (int i = 0; i <= medianIndex; i++) {
				if (point1 >= nums1.length) {
					median = nums2[point2];
					point2++;
					continue;
				}
				if (point2 >= nums2.length) {
					median = nums1[point1];
					point1++;
					continue;
				}
				if (nums1[point1] < nums2[point2]) {
					median = nums1[point1];
					point1++;
				} else {
					median = nums2[point2];
					point2++;
				}
			}
			mid = median;
		}
		return mid;
	}

時間複雜度爲O(m+n)

改進:

參考文章:https://segmentfault.com/a/1190000002988010

代碼:

	public static double findMedianSortedArrays1(int[] nums1, int[] nums2) {
        int m = nums1.length, n = nums2.length;
        int k = (m + n) / 2;
        if((m+n)%2==0){
            return (findKth(nums1,nums2,0,0,m,n,k)+findKth(nums1,nums2,0,0,m,n,k+1))/2;
        }   else {
            return findKth(nums1,nums2,0,0,m,n,k+1);
        }

	}

    private static double findKth(int[] arr1, int[] arr2, int start1, int start2, int len1, int len2, int k){
        // 保證arr1是較短的數組
        if(len1>len2){
            return findKth(arr2,arr1,start2,start1,len2,len1,k);
        }
        if(len1==0){
            return arr2[start2 + k - 1];
        }
        if(k==1){
            return Math.min(arr1[start1],arr2[start2]);
        }
        int p1 = Math.min(k/2,len1) ;
        int p2 = k - p1;
        if(arr1[start1 + p1-1]<arr2[start2 + p2-1]){
            return findKth(arr1,arr2,start1 + p1,start2,len1-p1,len2,k-p1);
        } else if(arr1[start1 + p1-1]>arr2[start2 + p2-1]){
            return findKth(arr1,arr2,start1,start2 + p2,len1,len2-p2,k-p2);
        } else {
            return arr1[start1 + p1-1];
        }
    }

時間複雜度:O(log(m+n))

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章