zoukankan      html  css  js  c++  java
  • [leetcode]Median of Two Sorted Arrays

    There are two sorted arrays A and B 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)).

    1. 第一次看到此题时,我的想法是现在A中折半查找缩小范围,比如取得A的中间数A[i],然后在B中找到A[i],然后便可以缩小范围。A中没有再找B。这个与最后的推荐做法有些类似。
    2. 错误或当时没想清楚的是,在B中找A[i]需要log(n)的时间,但其实不需要找A[i],直接找B[(m+n)/2 -i]作比较就行,是O[1]的时间,这样,整体就是O(log(n+m))。 此方法是在此处有描述:http://www2.myoops.org/course_material/mit/NR/rdonlyres/Electrical-Engineering-and-Computer-Science/6-046JFall-2005/30C68118-E436-4FE3-8C79-6BAFBB07D935/0/ps9sol.pdf
    3. 另外的方法是:http://leetcode.com/2011/03/median-of-two-sorted-arrays.html 这篇文章提到的方法自己也承认,太复杂太难写了。其思想是先找A的中位数和B的中位数比大小,然后可得到两个数组都可舍弃一半,但舍弃的时候两个数组要舍弃同样数目的数字,这样才能继续实施算法时,新数组们的中位数是原两数组的中位数。
    4. 一开始以为要对第一个和第二个中位数分别查找(n+m为偶数时),后来发现只要找到第一个中位数,第二个要么出现在同数组右边,要么在对应数组固定位置。
    5. 使用推荐的做法编程时,发现是个很难写对的程序,需要考虑很多情况,同时经常有小错误。
    6. 发现个小办法有点用:从最小的数组开始,然后慢慢变大。比如{1} {2,3} => {1,4} {2,3},这样能用较少的次数在纸上覆盖较多的情况。
    7. 先多列出一些test case。无论面试还是写程序,都会有好处。

    class Result
    {
        public int[] array;
    	public int index;
    }
    
    public class Solution {
        public double findMedianSortedArrays(int A[], int B[]) {
            // Start typing your Java solution below
            // DO NOT write main() function
        	
        	// special cases
        	if (A.length == 0){
        		if (B.length % 2 == 0)
        		{
        			return (B[B.length / 2 - 1] + B[B.length / 2]) / 2.0;
        		}
        		else
        		{
        			return B[B.length / 2];
        		}
        	}
        	else if (B.length == 0)
        	{
        		if (A.length % 2 == 0)
        		{
        			return (A[A.length / 2 - 1] + A[A.length / 2]) / 2.0;
        		}
        		else
        		{
        			return A[A.length / 2];
        		}
        	}
        	else if (A.length == 1 && B.length == 1)
        	{
        		return (A[0] + B[0]) / 2.0;
        	}
    
        	Result r = findMedFromFirstArray(A, B);
        	if (r.index == Integer.MIN_VALUE){
        		r = findMedFromFirstArray(B, A);
        	}
        	if (( A.length + B.length) % 2 == 0) // need to find med2
        	{
        		int med2 = findMed2(r, A, B);
        		return (r.array[r.index] + med2) / 2.0;
        	}
        	else
        	{
        		return r.array[r.index];
        	}
    
        }
    
        private Result findMedFromFirstArray(int A[], int B[])
        {
        	int la = 0;
        	int ra = A.length - 1;
        	int total = 0;
        	if (( A.length + B.length) % 2 == 0)
        	{
        		total = (A.length + B.length)/2 - 2;
        	}
        	else 
        	{
        		total = (A.length + B.length)/2 - 1;
        	}
        	while (la <= ra)
        	{
        		int mid = (la + ra) / 2;
        		int idx =  total - mid;
    
                if ((idx < 0 && (idx + 1) >= 0 && A[mid] <= B[idx + 1]) ||
                		(idx >= 0 && idx < B.length && idx + 1 >= B.length && B[idx] <= A[mid]) ||
        		    	(idx >= 0 && idx + 1 < B.length && B[idx] <= A[mid] && A[mid] <= B[idx + 1]))
        		{
        				Result r = new Result();
        				r.index = mid;
        				r.array = A;
        				return r;
        		}
    			if (idx >= B.length)
    			{
    				la = mid+1;
    			}
    			else if (idx < 0)
    			{
    				ra = mid-1;
    			}
    			else if (B[idx] > A[mid])
        		{
        			la = mid + 1;
        		}
    			else
    			{
    				ra = mid - 1;
    			}
        	}
        	Result r = new Result();
    		r.index = Integer.MIN_VALUE; // this means not find
    		r.array = A;
    		return r;
        }
        
        private int findMed2(Result r, int ArrayA[], int ArrayB[])
        {
        	int target1 = Integer.MAX_VALUE;
    		int target2 = Integer.MAX_VALUE;
    		int[] A = ArrayA;
    		int[] B = ArrayB;
    		if (r.array == B)
    		{
    			A = ArrayB;
    			B = ArrayA;
    		}
    		{
    			if (r.index + 1 < A.length)
    			{
    				target1 = A[r.index + 1];
    			}
    			int idx = ( A.length + B.length) / 2 - 2 - r.index + 1;
    			if (idx >= 0 && idx < B.length)
    			{
    				target2 = B[idx];
    			}
    			
    			if (target1 < target2)
    			{
    				return target1;
    			}
    			else
    			{
    				return target2;
    			}
    		}
        }
        	
    }
    

    Discuss上有这段代码,理解一下,基本上是在A中折半猜是不是中位数,A中没有后在B中猜。最后猜到B[j]<=A[i]<=B[j+1],此时,无论奇偶(2k+1或者2k个),A[i]都是第k+1那个。那么奇数时,A[i]是正中的那个;偶数时,A[i]是中位数两个里大的那个,小的那个要从B[j]和A[i-1]里选一个。

    double findMedian(int A[], int B[], int l, int r, int nA, int nB) {
    	if (l > r) 
    		return findMedian(B, A, max(0, (nA+nB)/2-nA), min(nB, (nA+nB)/2), nB, nA);
    	int i = (l+r)/2;
    	int j = (nA+nB)/2 – i – 1;
    	if (j ≥ 0 && A[i] < B[j]) return findMedian(A, B, i+1, r, nA, nB);
    	else if (j < nB-1 && A[i] > B[j+1]) return findMedian(A, B, l, i-1, nA, nB);
    	else {
    		if ( (nA+nB)%2 == 1 ) return A[i];
    		else if (i > 0) return (A[i]+max(B[j], A[i-1]))/2.0;
    		else return (A[i]+B[j])/2.0;
    	}
    }
    

      

  • 相关阅读:
    mysqlp批量替换的sql语句
    Paypal 支付功能的 C# .NET / JS 实现
    Layui table 组件的使用:初始化加载数据、数据刷新表格、传参数
    WinForm DataGridView 绑定泛型List(List<T>)/ArrayList不显示的原因和解决
    entity framework codefirst 用户代码未处理DataException,InnerException基础提供程序在open上失败,数据库生成失败
    《设计模式》一书中的23种设计模式
    C++程序实例唯一方案,窗口只打开一次,程序只打开一次
    重构——与设计模式的恋情
    重构——一个小例子
    C#通过调用WinApi打印PDF文档类,服务器PDF打印、IIS PDF打印
  • 原文地址:https://www.cnblogs.com/lautsie/p/3183086.html
Copyright © 2011-2022 走看看