求第k小数

https://leetcode.cn/problems/median-of-two-sorted-arrays/submissions/

/* 我们可以将取中位数问题转化为求第k小数问题:[ref_user:windliang]
由于两个数组都有序,所以我们每次可以分别在两个数组中取k/2个数:[a1~ak], [b1~bk]
然后比较ak和bk的大小,如果ak<bk,那么[a1~ak]都可以排除掉了,他们绝不会是第k小数
反之如果bk<ak,那么[b1~bk]就可以都排除掉了;如果相等,那么去掉哪一个都一样
另外就是需要注意k/2可能大于数组长度,此时直接取整个数组就可以了
*/
class Solution {
private:
    int getKth(vector<int> &nums1, int l1, int r1, vector<int> &nums2, int l2, int r2, int k) {
        int len1 = r1 - l1 + 1;
        int len2 = r2 - l2 + 1;
        // 让len1<=len2,这样如果数组长度小于k/2,一定是nums1
        if(len1 > len2) return getKth(nums2, l2, r2, nums1, l1, r1, k);
        
        // 递归结束的条件,要么是找到了第k小数,此时k递归为1
        // 要么是nums1数组长度为0,此时虽然没有找到第k小数,但是也无法继续往下递归了,也没必要继续往下递归了
        if(len1 == 0)   return nums2[l2 + k - 1];
        if(k == 1)  return min(nums1[l1], nums2[l2]);
        
        // 排除元素
        int i = l1 + min(len1, k / 2) - 1; // nums1[l1~i]
        int j = l2 + min(len2, k / 2) - 1; // nums2[l2~j]
        if(nums1[i] > nums2[j]) {
            return getKth(nums1, l1, r1, nums2, j + 1, r2, k - (j - l2 + 1));
        }
        return getKth(nums1, i + 1, r1, nums2, l2, r2, k - (i - l1 + 1));
    }
public:
    double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
        int n = nums1.size(), m = nums2.size();
        // 注意我们规定的是下标0是第1小数
        if((n + m) & 1) {
            return getKth(nums1, 0, n - 1, nums2, 0, m - 1, (n + m) / 2 + 1);
        }
        return (getKth(nums1, 0, n - 1, nums2, 0, m - 1, (n + m) / 2) 
              + getKth(nums1, 0, n - 1, nums2, 0, m - 1, (n + m) / 2 + 1)) * 0.5;
    }
};
posted @ 2024-09-25 23:17  光風霽月  阅读(6)  评论(0编辑  收藏  举报