• [Leetcode]4. 寻找两个正序数组的中位数


    题目描述

    给定两个大小为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。请你找出并返回这两个正序数组的中位数。

    进阶:你能设计一个时间复杂度为 O(log (m+n)) 的算法解决此问题吗?

    • 示例 1:
    输入:nums1 = [1,3], nums2 = [2]
    输出:2.00000
    解释:合并数组 = [1,2,3] ,中位数 2
    
    • 示例 2:
    输入:nums1 = [1,2], nums2 = [3,4]
    输出:2.50000
    解释:合并数组 = [1,2,3,4] ,中位数 (2 + 3) / 2 = 2.5
    
    • 示例 3:
    输入:nums1 = [0,0], nums2 = [0,0]
    输出:0.00000
    
    • 示例 4:
    输入:nums1 = [], nums2 = [1]
    输出:1.00000
    
    • 示例 5:
    输入:nums1 = [2], nums2 = []
    输出:2.00000
    

    第一种解法

    class Solution {
    
      public double findMedianSortedArrays(int[] nums1, int[] nums2) {
        int len1 = nums1.length;
        int len2 = nums2.length;
        int len3 = len1 + len2;
        int[] nums3 = new int[len3];
        int cur1 = 0;
        int cur2 = 0;
        int cur3 = 0;
        while (cur1 < len1 && cur2 < len2) {
          if (nums1[cur1] < nums2[cur2]) {
            nums3[cur3++] = nums1[cur1++];
          } else {
            nums3[cur3++] = nums2[cur2++];
          }
        }
        while (cur1 < len1) {
          nums3[cur3++] = nums1[cur1++];
        }
        while (cur2 < len2) {
          nums3[cur3++] = nums2[cur2++];
        }
        return (nums3[(len3 - 1) / 2] + nums3[len3 / 2]) / 2.0;
      }
    
      public static void main(String[] args) {
        int[] nums1 = {1};
        int[] nums2 = {2};
        System.out.println(new Solution().findMedianSortedArrays(nums1, nums2));
      }
    }
    

    将两个有序数组合并成一个有序数组,时间复杂度O(m+n),空间复杂度O(m+n)。

    第二种解法

    class Solution2 {
    
      public double findMedianSortedArrays(int[] nums1, int[] nums2) {
        int len3 = nums1.length + nums2.length;
        int k1 = findKthSmallest(nums1, nums2, (len3 - 1) / 2);
        int k2 = findKthSmallest(nums1, nums2, (len3) / 2);
        return (k1 + k2) / 2.0;
      }
    
      /**
       * 查找两个数组中第K小元素
       */
      private int findKthSmallest(int[] nums1, int[] nums2, int k) {
        int len1 = nums1.length;
        int len2 = nums2.length;
        int cur1 = 0;
        int cur2 = 0;
        int cur3 = 0;
        while (cur1 < len1 && cur2 < len2) {
          if (nums1[cur1] < nums2[cur2]) {
            if (cur3 == k) {
              return nums1[cur1];
            }
            cur1++;
            cur3++;
          } else {
            if (cur3 == k) {
              return nums2[cur2];
            }
            cur2++;
            cur3++;
          }
        }
        while (cur1 < len1) {
          if (cur3 == k) {
            return nums1[cur1];
          }
          cur1++;
          cur3++;
        }
        while (cur2 < len2) {
          if (cur3 == k) {
            return nums2[cur2];
          }
          cur2++;
          cur3++;
        }
        return -1;
      }
    
      public static void main(String[] args) {
        int[] nums1 = {1, 3};
        int[] nums2 = {2};
        System.out.println(new Solution2().findMedianSortedArrays(nums1, nums2));
      }
    }
    

    不合并数组,找到中位数所在位置,时间复杂度O(m+n),空间复杂度O(1)。

    第三种解法

    class Solution3 {
    
      public double findMedianSortedArrays(int[] nums1, int[] nums2) {
        int len3 = nums1.length + nums2.length;
        int k1 = findKthSmallest(nums1, 0, nums2, 0, (len3 + 1) / 2);
        int k2 = findKthSmallest(nums1, 0, nums2, 0, (len3 + 2) / 2);
        return (k1 + k2) / 2.0;
      }
    
      /**
       * 查找两个数组中第K小元素,K范围为[1,,len]
       */
      private int findKthSmallest(int[] nums1, int nums1Left, int[] nums2, int nums2Left, int k) {
        int len1 = nums1.length;
        int len2 = nums2.length;
        //第一个数组查找完,直接查找第二个数组
        if (nums1Left >= len1) {
          return nums2[nums2Left + k - 1];
        }
        //第二个数组查找完,直接查找第一个数组
        if (nums2Left >= len2) {
          return nums1[nums1Left + k - 1];
        }
        if (k == 1) {
          return Math.min(nums1[nums1Left], nums2[nums2Left]);
        }
        //中位数向下取整
        int middleVal1 =
            (nums1Left + k / 2 - 1 < len1) ? nums1[nums1Left + k / 2 - 1] : Integer.MAX_VALUE;
        int middleVal2 =
            (nums2Left + k / 2 - 1 < len2) ? nums2[nums2Left + k / 2 - 1] : Integer.MAX_VALUE;
        if (middleVal1 < middleVal2) {
          return findKthSmallest(nums1, nums1Left + k / 2, nums2, nums2Left, k - k / 2);
        } else {
          return findKthSmallest(nums1, nums1Left, nums2, nums2Left + k / 2, k - k / 2);
        }
      }
    
      public static void main(String[] args) {
        int[] nums1 = {1, 2};
        int[] nums2 = {3, 4};
        System.out.println(new Solution3().findMedianSortedArrays(nums1, nums2));
      }
    }
    

    使用二分查找,将问题转换成求两个数组中第K小元素的问题。时间复杂度O(log(m+n))。

  • 相关阅读:
    background之你不知道的background-position
    ES6学习笔记(二)
    ES6学习笔记(一)
    将博客搬至CSDN
    Mongodb的性能优化问题
    使用AngularJS实现的前后端分离的数据交互过程
    输出JS代码中的变量内容
    程序生成word与PDF文档的方法(python)
    python 2.7安装某些包出现错误:"libxml/xmlversion.h:没有那个文件或目录"
    Linux中安装配置spark集群
  • 原文地址:https://www.cnblogs.com/strongmore/p/14294839.html
Copyright © 2020-2023  润新知