LeetCode_Median of Two Sorted Arrays

题目:

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)).

意思是有两个已排好序的数组(经过检验,这里说的是升序),找出这两个数组的中位数(如果两数组数字个数的总和是奇数,则返回中间的那个数;如果个数之和是偶数,则返回中间两个数的平均数),并且题目中还限制了时间复杂度O(m+n)。

Java解题

用了两种方法,都通过了,一种很容易想到但不够优化,第二种比较好。

第一种:

假设两个数组合并为一个有序数组,计算出中位数的序号key(其实就是连个数组长度之和除以2),分别使用两个标记,或者说是指针,分别指向两个数组的第一个数字,将两个指针上的数字进行比较,较小的一方指针向后移动一个,同时,变量sum自增1,直到sum和key相等。需要注意的是:若两个数组中的其中一个若遍历完了还没有达到sum=key,则其余的只需要遍历另一个数组即可。

实现代码:

public static double findMedianSortedArrays(int[] nums1, int[] nums2) {
		int total=(nums1.length+nums2.length);
		if(total%2!=0)
			return find(nums1,nums2,(total+1)/2);
		else
			return (find(nums1,nums2,total/2)+find(nums1,nums2,total/2+1))/2;
	}
	
	public static double find(int[] nums1, int[] nums2,int key) {
		int i=0,j=0,sum=0,flag=0;
		while(sum!=key&&i<nums1.length&&j<nums2.length){
			flag=0;
		//	System.out.println("before---key:"+key+"------i:"+i+"-------j:"+j);
			if(nums1[i]<=nums2[j]){
				i++;
				flag=1;
			}
			else{
				j++;
				flag=2;
			}
		//	System.out.println("after---key:"+key+"------i:"+i+"-------j:"+j);
			sum++;
		}
		if(sum!=key){
		if(i>=nums1.length)
			while(sum!=key){
				j++;
				sum++;
				flag=2;
			}
		if(j>=nums2.length)
			while(sum!=key){
				i++;
				sum++;
				flag=1;
			}
		}
		if(flag==1)
			return nums1[i-1];
		else
			return nums2[j-1];
	}

第二种:

1、假设nums1数组比nums2数组元素少,key为中位数的序号,若key/2 < nums1.length 则令a=nums1[ key/2 ]  b=nums2[ key/2 ]

key/2 > nums1.length 则令a=nums1[ nums1.length ]  b=nums2[ key/2 - a ]

2、如果a<b 则在nums1数组中的位于a之前的所有元素都不可能存在我们想要找的那个中位数;反之,如果b<a,则在nums2数组中的位于b之前的所有元素都不可能存在我们想要找的那个中位数,在下次循环比较的时候就不考虑这些元素了。

代码实现:

public static double findMedianSortedArrays(int[] nums1, int[] nums2) {
		int total=(nums1.length+nums2.length);
		if(total%2!=0)
			return find(nums1, 0, nums1.length, nums2, 0, nums2.length, (total+1)/2);
		else
			return (find(nums1, 0, nums1.length, nums2, 0, nums2.length, total/2)+find(nums1, 0, nums1.length, nums2, 0, nums2.length, total/2+1))/2;
	}
	
	public static double find(int[] nums1,int st1,int length1, int[] nums2,int st2,int length2,int key) {
	//	System.out.println("st1:"+st1+"------length1:"+length1+"-----st2:"+st2+"------length2:"+length2+"----key:"+key);
		if(length2<length1)
			return find(nums2, st2,length2, nums1, st1,length1, key);
		if(length1==0)
			return nums2[st2+key-1];
		if(key==1)
			return Math.min(nums1[st1], nums2[st2]);
		int a=Math.min(length1, key/2);
		int b=key-a;
		if(nums1[st1+a-1]<nums2[st2+b-1]){
			return find(nums1, st1+a,length1-a, nums2, st2,length2, key-a);
		}
		else if(nums1[st1+a-1]>nums2[st2+b-1])
			return find(nums1, st1, length1, nums2, st2+b, length2-b, key-b);
		else 
			return nums1[st1+a-1];

	}

测试方法:

以上两种方法都可以用下边这个方法测试:

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int[] a = new int[]{2,4,6,8};
		int[] b = new int[]{3,5,9,10,12};
		System.out.println(findMedianSortedArrays(a,b));
	}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值