• 4.寻找两个正序数组的中位数 INnoVation


    思路

    原问题难以直接递归求解,所以我们先考虑这样一个问题:

    在两个有序数组中,长度分别为n、m, 找出第k小数。

    如果该问题可以解决,那么第 k = (n+m)/2 小数就是我们要求的中位数.

    先从简单情况入手,假设 m,n ≥ k/2,我们先从 nums1 和 nums2 中各取前 k/2 个元素:

    • 如果 nums1[k/2−1] > nums2[k/2−1],则说明 nums2 中的前 k/2 个元素一定都小于等于第 k 小数,所以我们可以先刨去这些数,将问题归约成在剩下的数中找第 k−⌊k/2⌋ 小数.
    • 如果 nums1[k/2−1] ≤ nums2[k/2−1]],可说明 nums1 中的前 k/2 个元素一定都小于等于第 k 小数,同样可将问题的规模减少一半.

    现在考虑边界情况,如果m<k/2,则我们从 nums1 中取m个元素,从nums2 中取 k/2 个元素(由于 k=(n+m)/2,因此 m,n 不可能同时小于 k/2.):

    • 如果 nums1[m−1]>nums2[k/2−1],则 nums2 中的前 k/2 个元素一定都小于等于第 k 小数,我们可以将问题归约成在剩下的数中找第 k−⌊k/2⌋ 小数.

    • 如果 nums1[m−1]≤nums2[k/2−1],则 nums1 中的所有元素一定都小于等于第 k 小数,因此第k小数是 nums2[k−m−1].

    时间复杂度分析:k=(m+n)/2,且每次递归 k 的规模都减少一半,因此时间复杂度是 O(log(m+n)).

    class Solution {
    public:
        double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
            int total = nums1.size() + nums2.size();
            if (total % 2 == 0){
                int left = findKthNumber(nums1, 0, nums2, 0, total / 2);
                int right = findKthNumber(nums1, 0, nums2, 0, total / 2 + 1);
                return (left + right) / 2.0;
            }else{
                return findKthNumber(nums1, 0, nums2, 0, total / 2 + 1);
            }
        }
    
        //这里指的是第K个数,而不是下标为K的数,比如1 2 3 4, 1是第1个数..以此类推
        int findKthNumber(vector<int> &nums1, int i, vector<int> &nums2, int j, int k){
          	//令num1总是较短的那一个
            if (nums1.size() - i > nums2.size() - j) return findKthNumber(nums2, j, nums1, i, k);
            //如果nums1走到了头,那nums2[j+k-1]就是中位数
          	if (nums1.size() == i) return nums2[j + k - 1];
          	//如果走到了答案所在位置,返回nums1[i]和nums[j]中相对小的那一个
            if (k == 1) return min(nums1[i], nums2[j]);
    
            // 每次淘汰K/2个数
            //找到nums1和nums2分别的中点,需要注意的是num1的长度可能小于k/2,所以i+k/2可能越界,需要取min值
            int si = min(i + k / 2, int(nums1.size())), sj = j + k / 2;
            if (nums1[si - 1] > nums2[sj - 1])
                return findKthNumber(nums1, i, nums2, sj, k - k / 2);
            else
                return findKthNumber(nums1, si, nums2, j, k - (si - i));
        }
    };
    

    Q1、if (nums1[si - 1] > nums2[sj - 1])

    寻找第k个最小的数,给出的是从1开始的下标,但是实际数组下标从0开始,因此需要减1
    比如: 1 2 3 4 5 6
    第3小的数是3,下标是2
    
  • 相关阅读:
    java经常出现的异常
    后台采用springmvc框架 前台bootstrap 实现对话框编辑信息
    List集合与Array数组之间的互相转换
    freemarker 设置文本内容超过一定长度 用省略号代替
    bootstrap实现多个下拉框同时搜索
    jquery 循环遍历选中的多选复选框checkbox
    同时对数据库进行更新,添加与删除操作
    获取页面内容封装成json对象
    前台bootstrap按钮动态添加与删除
    set 遍历
  • 原文地址:https://www.cnblogs.com/INnoVationv2/p/16869452.html
Copyright © 2020-2023  润新知