zoukankan      html  css  js  c++  java
  • LeetCode寻找两个有序数组的中位数

    题目:

    给定两个大小为 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
    来源:力扣(LeetCode)
    链接:https://leetcode-cn.com/problems/median-of-two-sorted-arrays
    著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
     
    方法:二分法
    将数组A左边i个元素和数组B右边j个元素
    使得i+j=(m-i)+(n-j)
     数组A剩下的len1-i和数组B剩下的len2-j个元素之和保持一致
    此时只要满足条件a[i-1]<b[j]&&b[j-1]<a[i]时,中位数就可得
    处理奇偶时,为保证i+j=(m+n)/2=>i+j=(m+n-1)/2 偶数=>不变 奇数平半分
    因为不能直接改变i和j所有用start和end来控制,或者说是i的范围
    int m=nums1.length,n=nums2.length;
            if(m>n)//保证len1<=len2
                return getZ(nums2,nums1);
            
            int start=0,end=m;
            int maxl = 0,minr = 0;
            
            while(start<=end) {
                int i=(start+end)/2;
                int j=(m+n+1)/2-i;
                
                if(i>start&&nums1[i-1]>nums2[j]) {//i太大应该变小,右边范围左移
                    end--;
                }else if(i<end&&nums2[j-1]>nums1[i]){//i太小应该变大,左边范围扩大
                    start++;
                }else {
                    maxl=(i==0)?nums2[j-1]:((j==0)?nums1[i-1]:(nums1[i-1]>nums2[j-1]?nums1[i-1]:nums2[j-1]));
                    if((m+n)%2!=0)
                        return maxl;
                    else
                        minr=(i==m)?nums2[j]:((j==n)?nums1[i]:(nums1[i]<nums2[j]?nums1[i]:nums2[j]));
                        return (maxl+minr)/2.0;
                }
            }
            return 0.0;

    过程中遇到的问题及理解:

    1,红色第一处以及红色第二处如果规定为(i>=1)(i<=m)执行时间会变长,或者是说start和end为什么可以代表i的范围

    2,此处的返回不能写在外面因为当m=0时,j可能会越界(如{}{1}这两个数组执行时),因此奇数时直接返回,而只有奇数时才会越界

    3,end--和start++的确定不太明白,还是想不通start和end为什么可以代表i的范围

    ###########################################################################

    更新:改变了下面红色代码,二分法不断选择正确的一半的区间

     int m=nums1.length,n=nums2.length;
      if(m>n)//保证len1<=len2
       return getZ(nums2,nums1);
      
      int start=0,end=m;
      int maxl = 0,minr = 0;
      
      while(start<=end) {
       int i=(start+end)/2;
       int j=(m+n+1)/2-i;
       
       if(i>start&&nums1[i-1]>nums2[j]) {//i太大应该变小,右边范围左移
        end=i-1;
       }else if(i<end&&nums2[j-1]>nums1[i]){//i太小应该变大,左边范围扩大
        start=1+i;
       }else {
        maxl=(i==0)?nums2[j-1]:((j==0)?nums1[i-1]:(nums1[i-1]>nums2[j-1]?nums1[i-1]:nums2[j-1]));
        if((m+n)%2!=0)
         return maxl;
        else
         minr=(i==m)?nums2[j]:((j==n)?nums1[i]:(nums1[i]<nums2[j]?nums1[i]:nums2[j]));
         return (maxl+minr)/2.0;
       }
      }
      return 0.0;

    问题是测试显示这个运行时间更长

  • 相关阅读:
    HDU 6143 Killer Names【dp递推】【好题】【思维题】【阅读题】
    HDU 6143 Killer Names【dp递推】【好题】【思维题】【阅读题】
    POJ 3974 Palindrome【manacher】【模板题】【模板】
    POJ 3974 Palindrome【manacher】【模板题】【模板】
    HDU 6127 Hard challenge【计算机几何】【思维题】
    HDU 6127 Hard challenge【计算机几何】【思维题】
    HDU 6129 Just do it【杨辉三角】【思维题】【好题】
    HDU 6129 Just do it【杨辉三角】【思维题】【好题】
    HDU 3037 Saving Beans【Lucas定理】【模板题】【模板】【组合数取余】
    8.Math 对象
  • 原文地址:https://www.cnblogs.com/code-fun/p/11438417.html
Copyright © 2011-2022 走看看