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

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

时间:2023-07-29 14:48:36浏览次数:49  
标签:正序 LC int 中位数 数组 n1 n2 nums1 nums2

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

题目描述

这是LeetCode 4、寻找两个正序数组的中位数,难度为 困难

给定两个大小分别为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。

请你找出并返回这两个正序数组的「中位数」。

示例:

输入:nums1 = [1,3], nums2 = [2]

输出:2.00000

解释:合并数组 = [1,2,3] ,中位数 2

朴素解法

最简单,也是最容易想到的思路就是,将两个数组进行合并排序,然后分别进行分类讨论,如果合并数组长度为奇数,则返回total/2位置的数字,如果是偶数,我们就返回 total/2(total - 1) / 2 位置的数字,并取其平均值。

此处有一小trick,我们可以直接将奇偶看作一种情况处理,得到的结果是一样的,这样就能避免分类讨论。

class Solution {
public:
    double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
        int m = nums1.size(), n = nums2.size();
        vector<int> ans(m + n);
        int i = 0;
        for(int n1 : nums1) ans[i++] = n1;
        for(int n2: nums2) ans[i++] = n2;
        sort(ans.begin(), ans.end());
        return (double(ans[ans.size() / 2]) + double(ans[(ans.size() - 1) / 2])) / 2;
    }
};

我们使用algorithm 中的sort函数进行排序,该排序算法时间复杂度为O(nlog(n))

  • 时间复杂度:合并两个数组的复杂度是 O(m + n),对合并数组进行排序的复杂度是 O(nlog(n))。整体复杂度是 O((m + n)log(m + n))
  • 空间复杂度:O(m + n)

分治解法

首先可以将原问题等效为:从两个有序数组中找到第k小的数字。

  1. 总数为奇数时:找到 第(total / 2)个小的数第(total / 2 + 1)个小的数
  2. 总数为偶数时:找到 第(total / 2 + 1)个小的数
具体思路为:
  • 默认第一个数组比第二个数组的有效长度短,如果不满足,则调换两个数组(这也是一个小trick,目的是减少边界处理工作;原本需要对两个数组做越界检查,现在只需要对短的数组做越界检查)
  • 第一个数组的有效长度从 i 开始,第二个数组的有效长度从 j 开始,其中 【i, si - 1】 是第一个数组的前 k / 2 个元素,【i, sj - i】 是第二个数组的前 k - k / 2 个元素 (为了确保 k 为奇数的时候正确)
  • nums[si - 1] > nums[sj - 1] : 则表示第 k 小一定不在 【j, sj - 1】 中,即在 【i, n】 或者 【sj, m】(如果不是这样子,凑不齐k个数字)
  • nums[si - 1] <= nums[sj - 1] : 则表示第 k 小一定不在 【i, si - 1】 中, 即在 【si, n】【j, m】
class Solution {
    public double findMedianSortedArrays(int[] nums1, int[] nums2) {
        int tot = nums1.length + nums2.length;
        if (tot % 2 == 0) {
            int left = find(nums1, 0, nums2, 0, tot / 2);
            int right = find(nums1, 0, nums2, 0, tot / 2 + 1);
            return (left + right) / 2.0;
        } else {
            return find(nums1, 0, nums2, 0, tot / 2 + 1);
        }
    }
    int find(int[] n1, int i, int[] n2, int j, int k) {
        //要确保第一个数组比第二个短
        if (n1.length - i > n2.length - j) return find(n2, j, n1, i, k);
        //如果当前已经将短的数组遍历完成了,说明一定不在短的数组里面,在长的数组里面,而且
        //这里 i >= n1.length 的意思是n1数组已经消耗殆尽,只有一个数组,那么就是n2[j + k - 1]
        if (i >= n1.length) return n2[j + k - 1];
        // 如果是找第一小的数组,直接返回两个数组的最小头即可
        if (k == 1) {
            return Math.min(n1[i], n2[j]);
        } else {
            int si = Math.min(i + (k / 2), n1.length), sj = j + k - (k / 2);
            if (n1[si - 1] > n2[sj - 1]) {
                // 我们就抛弃掉不符合要求的数组半边,但由于我们抛弃的半边其实是可以全部归结到小于第k个数的阵营去的
                // 所以我们只需要找k - 右半辣的数据的第k小的数字就行了
                return find(n1, i, n2, sj, k - (sj - j));
            } else {
                // 同理抛弃半边
                return find(n1, si, n2, j, k - (si - i));
            }
        }
    }
}
  • 时间复杂度:每次递归 k 的规模都减少一般,复杂度为 O(log(m + n))
  • 空间复杂度:O(1)

Label:二分,分治

标签:正序,LC,int,中位数,数组,n1,n2,nums1,nums2
From: https://www.cnblogs.com/superJade/p/17589773.html

相关文章

  • LC 3、无重复字符的最长子串
    LC3、无重复字符的最长子串给定一个字符串,请你找出其中不含有重复字符的【最长字串】的长度。示例:输入:s="abcabcbb"输出:3解释:因为无重复字符的最长子串是"abc",所以其长度为3。双指针+哈希表定义两个指针start和end表示当前处理的字串的头部和尾部,同时end......
  • 运动控制-PLC工作原理
    下面三个视频讲解了PLC工作原理,https://www.bilibili.com/video/BV1U34y1V7jQ/https://www.bilibili.com/video/BV1qF411F7ri/https://www.bilibili.com/video/BV1sW4y1k7B1/我的理解,我们的PLC程序就像是一个WinForms程序,由PLC操作系统启动后,然后PLC程序一直在运行,......
  • windows下shellcode注入的例子(WriteProcessMemory+CreateRemoteThread)
    vs里x64编译如下代码:  #include<iostream>#include<Windows.h>//#include"common.h"intmain(){ //msfvenom-pwindows/x64/execCMD=notepad.exe-fc unsignedcharshellcode[]= "\xfc\x48\x83\xe4\xf0\xe8\xc0\x00\x0......
  • VK1623LCD液晶屏显示驱动芯片,适用各种LCD面板显示
    产品品牌:永嘉微电/VINKA产品型号:VK1623S封装形式:LQFP100/QFP100/DICE/COG产品年份:新年份  产品简介:VK1623S是一个点阵式存储映射的LCD驱动器,可支持最大384点(48EGx8COM)的LCD屏。单片机可通过3/4线串行接口配置显示参数和发送显示数据,也可通过指令进入省电模式。Z20+167 ......
  • LC 2、两数相加
    LC2、两数相加这是LeetCode上的2、两数相加,难度为中等。 给你两个非空的链表,表示两个非负的整数。它们每位数字都是按照逆序的方式存储的,并且每个节点只能存储一位数字。 请你将两个数相加,并以相同形式返回一个表示和的链表。你可以假设除了数字0之外,这两个数都不......
  • LC 1、两数之和
    LC1、两数之和题目描述这是LeetCode上的1、两数之和,难度为简单。 给定一个整数数组nums和一个整数目标值target,请你在该数组中找出「和为目标值」的那「两个」整数,并返回它们的数组下标。 你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出......
  • 医学案例|配对wilcoxon符号秩检验
    一、案例介绍某单位想要研究某保健品对小鼠是否具有抗疲劳作用,将同种属的小鼠按性别与年龄相同、体重相近配成对子,共14对,并将每对中的两只小鼠随机分配到两个不同的保健食品剂量组,测量小鼠负重5%体重时的游泳时间(min),试比较不同剂量组的小鼠负重游泳时间有无差别。二、问题分析想......
  • linux内存日志 | journalctl指令
    摘要一、linux内存日志就是有些日志仅仅在系统允许过程中写在内存当中,但是并不会保存到硬盘当中重启后,内存日志就会情况二、指令指令功能说明选项journalctl查看全部journalctl-n3查看最新3条journalctl--since19:00--until19:10:10查看起始......
  • halcon01_halcon 联合C#导出
    01,halcon导出C#分为两种,一是导出C#语言,主要在action中进行封装二是,导出库工程,在导出库工程前,先保存halcon文件然后在导出库工程,将res_OUTTEST1文件夹拷贝在Debug文件夹下 ......
  • plsql develop 单步调试oralce存储过程
    单步调试是排查程序中逻辑错误的最直接的途径,sqlserver中调试非常方便,即F11即可进入调试模式。而oralce中的调试就需要进行一点点设置,这里记录一下plsqldevelop单步调试的方法:首先,要有调试权限否则报:调试报错,提示ORA-01031:insufficientprivileges,则说明当前用户权限不......