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

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

  • 相关阅读:
    jquery mobile左右滑动切换页面
    用phonegap和jquery-mobile写android应用
    javascript配置ckfinder的路径
    HTML5中表单验证的8种方法
    select标签中的选项分组
    c# 冒号:C#中两个冒号(::)的作用
    jquery validate
    【C#学习笔记】检测进程是否存在并关闭
    【C#学习笔记】载入图片并居中
    【C#学习笔记】鼠标控制
  • 原文地址:https://www.cnblogs.com/code-fun/p/11438417.html
Copyright © 2020-2023  润新知