首页 > 其他分享 >4.寻找两个正序数组的中位数

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

时间:2022-11-08 14:03:10浏览次数:39  
标签:正序 int 中位数 findKthNumber 数组 return nums1 nums2 小数

思路

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

在两个有序数组中,长度分别为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);
        }
    }

    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]);
     		//找到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

标签:正序,int,中位数,findKthNumber,数组,return,nums1,nums2,小数
From: https://www.cnblogs.com/INnoVationv2/p/16869452.html

相关文章

  • React组件设计模式-纯组件,函数组件,高阶组件
    一、组件(1)函数组件如果你想写的组件只包含一个render方法,并且不包含state,那么使用函数组件就会更简单。我们不需要定义一个继承于React.Component的类,我们可以定......
  • 力扣209 长度最小的子数组
    题目:给定一个含有 n 个正整数的数组和一个正整数target。找出该数组中满足其和≥target的长度最小的连续子数组 [numsl,numsl+1,...,numsr-1,numsr],并返回......
  • 【JavaScript 教程】第六章 数组03— Stack :使用 Array 的push()和pop()方法实现堆栈
    英文 | https://www.javascripttutorial.net/译文|杨小爱在上节,我们学习了JavaScriptArray length属性以及如何正确处理它,错过的小伙伴可以点击文章《​​【JavaScrip......
  • JavaScript数组去重—ES6的两种方式
    说明JavaScript数组去重这个问题,经常出现在面试题中,以前也写过一篇数组去重的文章,(JavaScript数组去重的多种方法原理详解)但感觉代码还是有点不够简单,今天和大家再说两种......
  • 实验4 类与数组、指针
    2022.11.02OOP实验课实验4类与数组、指针任务5代码:vectorInt54.hpp#pragmaonce#include<iostream>#include<cassert>#include<iomanip>usingnamespace......
  • 数组小和
    packageclass04;/***数组小和*在一个数组中,一个数左边比它小的数的总和,叫数的小和,所有数的小和累加起来叫数组的小和,求数组小和*/publicclassCode02_SmallS......
  • [???] 带权中位数
    好像是某道CF问题的变形,记一下.题目描述有若干的排列在一条直线上的点\(p_i\),每个点上有\(a_i\)个人,找出一个点,使得所有人移动带这个人的位置上的总距离最小.结......
  • 数组~Count digits from a text stream
    题目描述Countdigits,whitespaces(‘’,’\n’,’\t’)andothercharactersfromatextstreamendingwithEOF.输入AtextstreamendingwithEOF输出Pr......
  • 数组~插队
    题目描述有一个按照升序已排好的9个元素的数组,今输入一个数要求按原来排序的规律将它插入数组中。输入第一行,原始数列。第二行,需要插入的数字。输出排序后的数列......
  • 数学(环形数组) 数组 技巧 字符串
    918.环形子数组的最大和intsum=0,curMax=0,max=nums[0],curMin=0,min=nums[0];for(inti:nums){curMax=Math.max(curMax+i,i);max=Math.max......