LeetCode刷题day003 (Jieky)

LeetCode第4题

/*
There are two sorted arrays nums1 and nums2 of size m and n respectively.
Find the median of the two sorted arrays. The overall run time complexity should be O(log (m+n)).
You may assume nums1 and nums2 cannot be both empty.

Example 1:
nums1 = [1, 3]
nums2 = [2]
The median is 2.0

Example 2:
nums1 = [1, 2]
nums2 = [3, 4]
The median is (2 + 3)/2 = 2.5
*/
import java.lang.Math;
public class MedianofTwoSortedArrays {
     
	// 暴力破解,归并排序
	public double findMedianSortedArrays01(int[] num1,int[] num2){
     
		int n = num1.length;
		int m = num2.length; 
		
		if (n ==0 && m==0){
     
			return -1;
		}
		
		if (n == 0){
     
			if (m%2 == 0){
     
				return (num2[m/2 - 1] + num2[m/2])/2.0;
			}else{
     
				return num2[m/2];
			}
		}
		
		if (m == 0){
     
			if (n%2 == 0){
     
				return (num1[n/2 - 1] + num1[n/2])/2.0;
			}else{
     
				return num2[n/2];
			}
		}
		
		// 归并数组存储
		int[] nums = new int[m + n];
		// i,j分别做num1、num2的移动索引;count做nums的移动索引
		int i = 0,j = 0,count = 0;
		while(count < m + n){
     
			// num1的数据归并完毕,直接将num2全部一如nums
			if (i == n){
     
				while(j < m){
     
					// 每次count指向即将插入的空位,j对应即将移动
					nums[count++] = num2[j++];
				}
				// 到这里表示归并完成,跳出循环
				break;
			}
			
			// 同上
			if (j == m){
     
				while(i < n){
     
					nums[count++] = num1[i++];
				}
			}
			
			// 两个数值都未归并完成,i、j指向小的数据被归并
			if(num1[i] < num2[j]){
     
				nums[count++] = num1[i++];
			}else{
     
				nums[count++] = num2[j++];
			}
		}
		if (count%2 == 0){
     
			return (nums[count/2 - 1] + nums[count/2])/2.0;
		}else{
     
			return nums[count/2];
		}
	}
	
	// 事实上并不需要将两个数组进行真正的归并,
	// 我们只需要指导中位数的位置。
	// 两个数组的总长为奇数或偶数,需要遍历 len / 2 + 1 次
	public double findMedianSortedArrays02(int[] num1,int[] num2){
     
		int m = num1.length;
		int n = num2.length;
		int len = m + n;
		// 为了同时能够处理len为奇数和偶数的情况,
		// 定义两个变量,一个包含当前的数,一个保存当前边的数
		int left = -1,right = -1;
		// i、j分别是num1、num2的索引
		int i = 0, j = 0,count = 0;
		// 在退出循环之前,i、j必须移动其中一个
		while(count < len/2 + 1){
     
			left = right;
			// 保证num1还没有遍历完的情况下,判断是否移动i。
			// 判断是否是移动i,j >= n保证num2不会越界。
			if (i < m && (j >= n || num1[i] < num2[j])){
     
				right = num1[i++];
			}else{
     
				right = num2[j++];
			}
			// 对循环的次数计数
			count++;
		}
		
		if (len % 2 == 0){
     
			return (right + left)/2.0;
		}else{
     
			return right;
		}
	}
	
	// 二分法的时间复杂度?尾递归?
	// 使用求第k个最小数的算法
	public double findMedianSortedArrays03(int[] num1,int[] num2){
     
		// String的length带括号,int的length不带括号
		int n = num1.length;
		int m = num2.length;
		// 统一就问题,left、right指定的是第几个最小数
		int left = (n + m + 1) / 2;
		int right = (n + m + 2) / 2; 
		double getKthLeft = getKth(num1,0,n-1,num2,0,m-1,left);
		double getKthRight = getKth(num1,0,n-1,num2,0,m-1,right);
		// n + m 为奇数时,left 与 right相等,统一了奇偶长度的问题
		return (left + right) / 2.0;
	}
	// start、end、k分别指的是剩下数组开始的索引和结束的索引,
	// 以及要求的第k个数的标记
	public double getKth(int[] num1,int start1,int end1,int[] num2,int start2,int end2,int k){
     
		// 两个停止条件,其中一个数组为空(不可能两个空),或者k=1
		int len1 = end1 - start1 + 1;
		int len2 = end2 - start2 + 1;
		if(len1 > len2){
     
			// 保证若找到第k个小数之前若有数组为空,一定是num1先空
			// 递归过程中用于反转的层
			return getKth(num2,start2,end2,num1,start1,end1,k);
		}
		
		// 其中一个数值为空,这个数值一定num1,前面的判断的有力保证
		if (len1 == 0){
     
			// 一个数组为空的停止条件满足
			return num2[start2 + k - 1];
		}
		
		if(k == 1){
     
			// k=1的停止条件满足
			return Math.min(num1[start1],num2[start2]);
		}
		
		// 一定要保证数值索引不越界,k/2(向下取整)
		// 一定要牢记,在递归过程中,k是一个相对当前保留数组的数
		int i = start1 + Math.min(len1,k/2) - 1; 
		int j = start2 + Math.min(len2,k/2) - 1; 
		
		// 主要重复迭代这个部分
		if(num1[i] > num2[j]){
     
			// j以及j之前的数丢弃
			return getKth(num1,start1,end1,num2,j + 1,end2,k - (j - start2 + 1));
		}else{
     
			// i以及i之前的数丢弃
			return getKth(num1,i + 1,end1,num2,start2,end2,k - (i - start1 + 1));
		}
	}
	
	public static void main(String[] args){
     
		int[] nums1 = {
     1,2};
		int[] nums2 = {
     3,4};
		
		MedianofTwoSortedArrays instance = new MedianofTwoSortedArrays();
		
		double result = instance.findMedianSortedArrays03(nums1,nums2);
		System.out.println(result);
	}
}

你可能感兴趣的:(LeetCode,leetcode,java)