leetcode004 寻找两个有序数组的中位数

独自空忆成欢 提交于 2020-01-09 03:32:28

题目描述

给定两个大小为 m 和 n 的有序数组 nums1 和 nums2

请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n))。

你可以假设 nums1 和 nums2 不会同时为空。

解法1 

依次遍历这两个有序数组的元素,如果长度分别为len1,len2直到找到第(len1+len2)/2的元素

class Solution {
    public double findMedianSortedArrays(int[] nums1, int[] nums2) {
        int n1 = nums1.length;
        int n2 = nums2.length;
        
        int i = 0;
        int j = 0;
        int[] array = new int[(n1 + n2) / 2 + 1];
        
        int index = 0;
        // 找到第(n1+n2)/2小的数
        while(index < array.length) {
            if (i < n1 & j < n2) {
                if (nums1[i] < nums2[j]) {
                    array[index++] = nums1[i++];
                } else {
                    array[index++] = nums2[j++];
                }
            } else if (i >= n1) {
                array[index++] = nums2[j++];
            } else {
                array[index++] = nums1[i++];
            }
        }
        
        if((n1 + n2) % 2 == 0) {
            return 0.5*(array[array.length - 1] + array[array.length - 2]);
        } else {
            return array[array.length - 1];
        }
    }
}
View Code

时间复杂度O(m+n)

空间复杂度O(m+n)

解法2

分治法解题思路:
1. 首先是递归函数的定义,作用是寻找两个有序数组nums1中[left1, right1]和nums2数组[left2,right2]范围内第k小的数,k从1开始
2. 用n1纪录nums1数组中寻找范围的长度,用n2来记录nums2数组中寻找范围的长度
3. 如果要寻找的k大于n1 + n2,直接抛出异常
4. 如果n1>n2,将递归调用该函数,不过将与nums1数组有关的参数与nums2有关的参数进行换位,这样确保后期操作都是在n1 <= n2的条件下进行的。
5. 终止条件:
a. 当n1为0时,说明直邮一个数组中有元素,直接取该数组中第left2+k-1位元素即可
b. 当k为1时,说明我们要取的两个有序数组中的最小值直接返回两个数组第一个元素较小值即可

public double findMedianSortedArrays(int[] nums1, int[] nums2) {
        
        int n1 = nums1.length;
        int n2 = nums2.length;
        if (n1 == 0 && n2 == 0) {
            throw new IllegalArgumentException("两个数组长度为0");
        }
        int mid1 = findKthInTwoArrays(nums1, 0, n1-1, nums2, 0, n2-1, (n1 + n2) /2 + 1);
        if ((n1 + n2) % 2 != 0) {
            return mid1;
        } else {
            int mid2 =  findKthInTwoArrays(nums1, 0, n1-1, nums2, 0, n2-1, (n1+n2)/2);
            return 0.5* (mid1 + mid2);
        }   
    }
    private int findKthInTwoArrays(int[] nums1, int left1, int right1, int[] nums2, int left2, int right2, int k) {
        int n1 = right1 - left1 + 1;
        int n2 = right2 - left2 + 1;
        if (k > n1 + n2) {
            throw new IllegalArgumentException("k的值过大");
        }
        if (n1 == 0) {
            return nums2[left2 + k - 1];
        }
        if (n2 == 0) {
            return nums1[left1 + k - 1];
        }
        if (k == 1) {
            return Math.min(nums1[left1], nums2[left2]);
        }
        int i = Math.min(n1, k/2);
        int j = Math.min(n2, k/2);
        
        if(nums1[left1 + i - 1] > nums2[left2 + j - 1]) {
            return findKthInTwoArrays(nums1, left1, right1, nums2, left2 + j, right2, k - j);
        }else {
            return findKthInTwoArrays(nums1, left1 + i, right1, nums2, left2, right2, k - i);
        }
    }
}
View Code

时间复杂度O(lg(m+n))

空间复杂度O(n)

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!