LeetCode 4. 寻找两个正序数组的中位数***Hard

基本思想:

看到Ologn直接想二分;

这个二分查找不同于查中间值,而是更像是进行部分排除;

对于奇数或者偶数有序序列,查找中位数,相当于查找第k个值;

对于奇数个个数,相当于查找第(n+1)/2个值,而对于偶数个个数,相当于查找第n/2和n/2+1个数字,注意一下,这里下标都是从1开始计数;

对于查找第k个数字,则采用对半查询进行排除;

对于两个序列,分别为m,n大小,并且各自有序;

假设起始坐标都为0,则计算k/2-1,则两个序列的对比范围为: [ 0 , k / 2 − 1 ] [0,k/2-1] [0,k/21]

n u m 1 [ k / 2 − 1 ] > n u m 2 [ k / 2 − 1 ] num1[k/2-1]>num2[k/2-1] num1[k/21]>num2[k/21],则说明num2的前k/2个元素全部小于 n u m 1 [ k / 2 − 1 ] num1[k/2-1] num1[k/21],因此可以将这部分排除;

此时相当于从剩余的部分中寻找第 k − k / 2 k-k/2 kk/2个数,循环至k=1;

之所以循环到k=1,是因为k/2-1=0,此时只需要从两个有序序列的标记索引中二选一即可;

需要注意的地方:

  1. 索引+k/2-1的时候会越界,这里一定要注意;
  2. 如果一个序列遍历完,只需要返回另一个序列的第k个元素即可;

具体代码:

class Solution {
public:
    double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
        int total = nums1.size() + nums2.size();
        if (total % 2 == 1) {
            return fun(nums1, nums2, (total + 1) / 2);
        }
        else {
            return (fun(nums1, nums2, total / 2) + fun(nums1, nums2, total / 2 + 1))/2.0;
        }
    }

    double fun(vector<int>& nums1, vector<int>& nums2, int k) {
        int m = nums1.size();
        int n = nums2.size();
        int index1 = 0, index2 = 0;
        while (1) {
            if (m == index1) {
                return nums2[index2 + k - 1];
            }
            if (n == index2) {
                return nums1[index1 + k - 1];
            }
            if (k == 1) {
                return min(nums1[index1], nums2[index2]);
            }
            int newindex1 = min(m - 1, index1 + k / 2 - 1);
            int newindex2 = min(n - 1, index2 + k / 2 - 1);
            if (nums1[newindex1] <= nums2[newindex2]) {
                k -= newindex1 - index1 + 1;
                index1 = newindex1 + 1;
            }
            else {
                k -= newindex2 - index2 + 1;
                index2 = newindex2 + 1;
            }
        }
    }
};

你可能感兴趣的:(LeetCode刷题记录,leetcode,贪心算法,动态规划)