0
点赞
收藏
分享

微信扫一扫

CodeTop046 寻找两个正序数组的中位数

雅典娜的棒槌 2022-03-12 阅读 64

寻找两个正序数组的中位数

首先先判断两个数组的总长度是奇数还是偶数
奇数的话返回中间那个,偶数的话要返回中间两个的均值.
然后核心是寻找两个数组中第K大的元素 所以主要是后面那个方法!!!

public class Solution046 {
    public static void main(String[] args) {
        int[] nums1 = new int[]{1,2}, nums2 = new int[]{3,4};
        System.out.println(findMedianSortedArrays(nums1,nums2));
    }

    public static double findMedianSortedArrays(int[] nums1, int[] nums2) {
        int total = nums1.length + nums2.length;
        if (total % 2 == 1) {//一共奇数个元素 所以直接返回中间那个就行
            return fingKthElement(nums1, nums2, total / 2 + 1);
        } else {//一共偶数个元素 要返回中间两个的平均值
            int mid = total / 2;
            double ans = (fingKthElement(nums1, nums2, mid) + fingKthElement(nums1, nums2, mid + 1)) / 2.0;
            return ans;
        }

    }

    //寻找两个数组中第K大的元素
    public static int fingKthElement(int[] nums1, int[] nums2, int k) {
        /*基本思想:要寻找第K大的元素 分别判断nums1[k/2-1]和nums2[k/2-1]的大小
        如果nums1[k/2-1]<=nums2[k/2-1] 那么就算nums2的前k/2-1个元素都比你小 你也不过是第(k/2-1)+1+(k/2-1)=k-1个元素 所以可以排除了
        这样的话 就可以nums1就在[k/2+1,len1]之间查找 nums2没变 然后现在要找的就是第k-((k/2-1)+1)个元素了
        反之亦然!
        * */


        int len1 = nums1.length, len2 = nums2.length;
        int index1 = 0, index2 = 0;

        while (true) {
            //边界情况
            if (index1 == len1) return nums2[index2 + k - 1];
            if (index2 == len2) return nums1[index1 + k - 1];
            if (k == 1) return Math.min(nums1[index1], nums2[index2]);

            //正常情况
            int half = k / 2;
            int newindex1 = Math.min(len1, index1 + half) - 1;//要判断一下当前的index1+half是否已经超出了数组的边界 如果超出的话 只能使用数组的最后一个元素进行比较
            int newindex2 = Math.min(len2, index2 + half) - 1;

            if (nums1[newindex1] <= nums2[newindex2]) {//说明newindex1之前(包括newindex1)的元素都不可能是答案 可以排除了
                k = k - (newindex1 - index1 + 1);
                index1 = newindex1 + 1;
            } else {
                k = k - (newindex2 - index2 + 1);
                index2 = newindex2 + 1;
            }
        }
    }


}

整个算法的核心其实就在寻找两个数组中第K大的元素
这里的基本思想是:

  • 要寻找第K大的元素 分别判断nums1[k/2-1]和nums2[k/2-1]的大小
  • 如果nums1[k/2-1]<=nums2[k/2-1] 那么就算nums2的前k/2-1个元素都比你小 你也不过是第(k/2-1)+1+(k/2-1)=k-1个元素 所以可以排除了
  • 这样的话 就可以nums1就在[k/2+1,len1]之间查找 nums2没变 然后现在要找的就是第k-((k/2-1)+1)个元素了
  • 反之亦然!
//寻找两个数组中第K大的元素
    public static int fingKthElement(int[] nums1, int[] nums2, int k) {
        /*基本思想:要寻找第K大的元素 分别判断nums1[k/2-1]和nums2[k/2-1]的大小
        如果nums1[k/2-1]<=nums2[k/2-1] 那么就算nums2的前k/2-1个元素都比你小 你也不过是第(k/2-1)+1+(k/2-1)=k-1个元素 所以可以排除了
        这样的话 就可以nums1就在[k/2+1,len1]之间查找 nums2没变 然后现在要找的就是第k-((k/2-1)+1)个元素了
        反之亦然!
        * */


        int len1 = nums1.length, len2 = nums2.length;
        int index1 = 0, index2 = 0;

        while (true) {
            //边界情况
            if (index1 == len1) return nums2[index2 + k - 1];
            if (index2 == len2) return nums1[index1 + k - 1];
            if (k == 1) return Math.min(nums1[index1], nums2[index2]);

            //正常情况
            int half = k / 2;
            int newindex1 = Math.min(len1, index1 + half) - 1;//要判断一下当前的index1+half是否已经超出了数组的边界 如果超出的话 只能使用数组的最后一个元素进行比较
            int newindex2 = Math.min(len2, index2 + half) - 1;

            if (nums1[newindex1] <= nums2[newindex2]) {//说明newindex1之前(包括newindex1)的元素都不可能是答案 可以排除了
                k = k - (newindex1 - index1 + 1);
                index1 = newindex1 + 1;
            } else {
                k = k - (newindex2 - index2 + 1);
                index2 = newindex2 + 1;
            }
        }
    }
举报

相关推荐

0 条评论