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

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

代碼如下:

package com.likou;


/**
 * 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
 */
public class day04 {


    public static void main(String[] args) {
        int[] nums1={1,2};
        int[] nums2={3};
       double s= findMedianSortedArrays1(nums1,nums2);
       double s1=findMedianSortedArrays2(nums1,nums2);
        System.out.println(s1);
    }

    /**
     * 簡單暴力法,先將2個數組合並,兩個有序數組的合併也是歸併排序中的一部分。然後根據奇數,還是偶數
     * ,返回中位數
     * @param nums1
     * @param nums2
     * @return
     */
    public static double findMedianSortedArrays1(int[] nums1,int[] nums2){
        int[] nums;
       int m=nums1.length;
       int n=nums2.length;
       //合併數組,創建數組
       nums= new int[m+n];
       if(m == 0){
          if(n % 2 ==0){
              //偶數求中位數  數組下標從0開始
                return (nums2[n / 2 - 1]+nums2[n / 2]) / 2.0;
          }else {
              //不爲0 直接取中位數
              return nums2[n / 2];
          }
       }
       if(n == 0){
           if(m % 2 ==0){
               //偶數求中位數  數組下標從0開始
               return (nums2[m / 2 - 1]+nums2[m / 2]) / 2.0;
           }else {
               //不爲0 直接取中位數
               return nums2[m / 2];
           }

       }
       int count = 0;
       int i=0;
       int j=0;
        while (count != (m+n)){
           if(i == m){
               while (j != n){
                   nums[count++]=nums2[j++];
               }
               break;
           }
           if(j == n){
               while (i != m){
                   nums[count++]=nums2[i++];
               }
               break;
           }
           if(nums1[i] < nums2[j]){
               nums[count++] = nums1[i++];
           }else {
               nums[count++]= nums2[j++];
           }
        }
        if(count % 2 == 0){
           return (nums[count/2 -1]+nums[count/2]) /2.0;
        }else {
           return nums[count /2];
        }

    }

    /**
     * 思路:
     * 我們首先理一下中位數的定義
     * 中位數又稱中值,統計學中的專有名詞,代表一個樣本或種羣,概率分佈,中的一個數值
     * 可以將數值集合分爲相等的上下兩部分
     * 所以我們要對數組進行切割
     * 一個長度爲m的數組,有0到m總共m+1個位置可以切。
     */
    public static double findMedianSortedArrays2(int[] A,int[] B) {
        int m = A.length;
        int n = B.length;
        if (m > n) {
            return findMedianSortedArrays2(B, A);//保證M<=n
        }
        int iMin = 0, iMax = m;
        while (iMin <= iMax) {
            int i = (iMin + iMax) / 2;
            int j = (m + n + 1) / 2 - i;
            if (j != 0 && i != m && B[j - 1] > A[i]) {
                //i需要增大
                iMin = i + 1;
            } else if (j != 0 && i != n && B[j - 1] > B[i]) {
                iMax = i - 1;//i需要減少

            } else {
                //達到要求並將邊界條件例出來單獨考慮
                int maxLeft = 0;
                if (i == 0) {
                    maxLeft = B[j - 1];
                } else if (j == 0) {
                    maxLeft = A[i - 1];
                } else {
                    maxLeft = Math.max(A[i - 1], B[j - 1]);
                }
                    if((m+n) % 2 ==1){
                        return maxLeft;//奇數的話不考慮右半部分
                    }
                    int minRight = 0;
                    if(i==m){
                        minRight = B[j];
                    }else if(j == n){
                        minRight = A[i];
                    }else {
                        minRight = Math.max(B[j],A[i]);
                    }
                    return (maxLeft+minRight)/2.0;
                }
            }
        return 0.0;
    }


}

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