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;
}
}