数组-两个升序数组中位数

一、题目描述

二、解题思路

(一).基本思想:

如果列表总长度allsize( =arr1.size()+arr2.size() ) 为奇数时,中位数位置应该在两个列表排序后的第 allsize/2 位置处,如果allsize为偶数,中位数应该取 (allsize/2)-1 和 allsize/2 的平均数。

设置两个指针p1、p2,一个指向列表 arr1[0] ,一个指向列表 arr2[0] ,比较两个指针指向列表的值,值较小的指针往后移动一位

再次比较p1、p2,重复上述动作。

(二).注意:因为两个列表长度不一定相同,所以存在某一个指针p1遍历到列表末尾,但是仍然没有找到中位数,这时候中位数有可能就会出现①p1、p2均在列表中间,此时取二者较小值或者平均值、②在另一个列表中、③另一个列表中两个元素取平均值、④p1(此时在末尾)和p2取平均值、⑤p1(此时在末尾)这几种情况,下面就对各种可能出现的情况进行举例说明,以写出比较严谨的代码实现,覆盖各种可能出现的情况。

比较次数和总列表长度的奇偶性还有确定中位数位置是有关联性的,这一点可以自己在下面例子里尝试一下。

1.当allsize为奇数时:只存在一个中位数,此时比较次数为 allsize/2 次

(1).p1、p2在中间位置

        [1,2,3,8,9] 和 [4,5,6,7] ,总列表 [1,2,3,4,5,6,7,8,9]

        总长度为9,比较4次:

                第一次 p1->1,p2->4,p1<p2,p1++;

                第二次 p1->2,p2->4,p1<p2,p1++;

                第三次 p1->3,p2->4,p1<p2,p1++;

                第四次 p1->8,p2->4,p1>p2,p2++;

                此时:p1->8,p2->5 取二者较小值为5,中位数为5

(2).p1在arr1末尾,并且p1<=p2时

        [1,2,3,4]和[5,6,7,8,9],总列表 [1,2,3,4,5,6,7,8,9]

        总长度为9,比较4次:

                第一次 p1->1,p2->5,p1<p2,p1++;

                第二次 p1->2,p2->5,p1<p2,p1++;

                第三次 p1->3,p2->5,p1<p2,p1++;

                第四次 p1->4,p2->5,p1<p2,此时p1已经在末尾,不再++,设置变量标记中位数在arr2中(p2侧);

                此时:直接取p2为中位数,中位数为5

(3).p1在arr1末尾,并且p1>p2时

        [1,2,3,5]和[4,6,7,8,9],总列表 [1,2,3,4,5,6,7,8,9]

        总长度为9,比较4次:

                第一次 p1->1,p2->4,p1<p2,p1++;

                第二次 p1->2,p2->4,p1<p2,p1++;

                第三次 p1->3,p2->4,p1<p2,p1++;

                第四次 p1->5,p2->4,p1>p2,此时p2++;

                此时:p1->5,p2->6 取p1、p2二者较小值,中位数为5

2.当allsize为偶数时,中位数等于中间两个元素取平均值,此时两个元素比较次数为 allsize/2 -1 次,执行完allsize/2 -1 次判断时: 

(1).p1、p2在中间位置,并不能确定中间两个数在哪一侧产生,可能是两侧各贡献一个(包括p1或者p2没有发生移动的情况)

        两侧各贡献一个:

        (这种情况牛客里面的测试用例没有覆盖这种情况,刚开始我写的代码这部分有缺陷,所以会出现问题,下面的代码实现已经补上了处理策略,判断过程看下面加粗黄色说明部分)

        [1,2,3,8,9] 和 [4,5,6,7,10] ,总列表 [1,2,3,4,5,6,7,8,9,10]

        总长度为10,比较4次:

                第一次 p1->1,p2->4,p1<p2,p1++;

                第二次 p1->2,p2->4,p1<p2,p1++;

                第三次 p1->3,p2->4,p1<p2,p1++;

                第四次 p1->8,p2->4,p1>p2,p2++;

                此时:p1->8,p2->5,最后一次移动的是p2(作为求平均数的左值),且p2未到达末尾,需要比较(p2+1)和p1位置的值,(p2+1)->6,p1->8,取二者较小值为6,中位数为(5+6)/2=5.5

        

        [4,5,6,7,10] 和 [1,2,3,8,9] ,总列表 [1,2,3,4,5,6,7,8,9,10]

        总长度为10,比较4次:

                第一次 p2->4,p1->1,p1>p2,p2++;

                第二次 p1->4,p2->2,p1>p2,p2++;

                第三次 p1->4,p2->3,p1>p2,p2++;

                第四次 p1->4,p2->8,p1<p2,p1++;

                此时:p1->5,p2->8,最后一次移动的是p1(作为求平均数的左值),且p1未到达末尾,需要比较(p1+1)和p2位置的值,(p1+1)->6,p1->8,取二者较小值为6,中位数为(5+6)/2=5.5


        p1或者p2没有发生移动的情况:

        [1,2,3,7]和[4,5,8,9],总列表 [1,2,3,4,5,7,8,9]

        总长度为8,比较3次:

                第一次 p1->1,p2->4,p1<p2,p1++;

                第二次 p1->2,p2->4,p1<p2,p1++;

                第三次 p1->3,p2->4,p1<p2,p1++;

                此时:p1->7,p2->4  需要比较一下p1和p2+1位置的大小,如果p1>p2+1,中位数选择p2和p2+1位置元素和的平均值;如果p1<p2+1,中位数选择p1和p2的平均值。

                

        [4,5,8,9] 和 [1,2,3,7],总列表 [1,2,3,4,5,7,8,9]

        总长度为8,比较3次:

                第一次 p1->4,p2->1,p1>p2,p2++;

                第二次 p1->4,p2->2,p1>p2,p2++;

                第三次 p1->4,p2->3,p1>p2,p2++;

                此时:p1->4,p2->7 需要比较一下p2和p1+1位置的大小,如果p2>p1+1,中位数选择p1和p1+1位置元素和的平均值;如果p2<p1+1,中位数选择p1和p2的平均值。


        并不能确定是否只出现在一侧的情况:

        [1,8] 和 [4,5,6,7,8,9],总列表 [1,4,5,6,7,8,8,9]

        总长度为8,比较3次:

                第一次 p1->1,p2->4,p1<p2,p1++;

                第二次 p1->8到达末尾,p2->4,p1>p2,p2++;

                第三次 p1->8到达末尾,p2->5,p1>p2,p2++;

                此时:p1->8,p2->6  p1到达末尾,p2一定是中间两个数之一,需要比较一下p2+1和p1的大小,取较小值作为另一个数,p2+1->7,p1->8,取p2+1和p2的平均数作为中位数,值为6.5。

(2).p1早已到达arr1末尾,确定两个数确定在p2侧产生

         [6,7] 和 [5,9,10,11,12,13],总列表 [5,6,7,9,10,11,12,13]

        总长度为8,比较3次:

                第一次 p1->6,p2->5,p1>p2,p2++;

                第二次 p1->6,p2->9,p1<p2,p1++;

                第三次 p1->7到达末尾,p2->9,p1<p2,p2++,且设置标志位;

                此时:中间两个数只会是p2和p2+1位置的值,计算两个数的平均数:p2->9,(p2+1)->10,平均值为8.5。

(3).p2早已到达arr2末尾,中间两个数确定在p1侧产生,这个执行过程大家自己根据上面(2)的过程推理一下。

       [5,9,10,11,12,13] 和 [6,7],总列表 [5,6,7,9,10,11,12,13]

三、代码实现

import java.util.*;

public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     *
     * @param nums1 int整型ArrayList
     * @param nums2 int整型ArrayList
     * @return double浮点型
     */
    public double Median (ArrayList<Integer> nums1, ArrayList<Integer> nums2) {
        double res = 0;
        int allsize = nums1.size() + nums2.size();
        int mididx = allsize / 2;
        int icounter=0;
        boolean oddnum=false;//奇数数
        if(allsize%2!=0){
            oddnum=true;//此时根据side判断取哪一侧的值,如果没有出现倾斜情况,则取p1、p2较小值
            icounter=mididx;
        }else{
            oddnum=false;//此时取p1和p2位置平均值
            icounter=mididx-1;
        }
        int p1 = 0, p2 = 0;
        boolean p1side=false,p2side=false;
        int lastestmove=0;
        while (icounter > 0) {
            if (p1 < (nums1.size() - 1) && nums1.get(p1) <= nums2.get(p2)) {
                p1++;
                lastestmove=1;
            }else if(p1 == (nums1.size() - 1)){
                if(!oddnum){
                    if(!p2side&&nums1.get(p1)>nums2.get(p2)){
                        p2++;
                        lastestmove=2;
                    }else if(!p2side&&nums1.get(p1)<=nums2.get(p2)){
                        p2side=true;
                    }else{
                        p2++;
                        lastestmove=2;
                    }    
                }else{
                    if(!p2side&&nums1.get(p1)>nums2.get(p2)){
                        p2++;
                        lastestmove=2;
                    }else{
                        if(!p2side){
                            p2side=true;
                        }else{
                            p2++;
                            lastestmove=2;
                        }
                    }
                }
            }else if (p2 < (nums2.size() - 1) && nums1.get(p1) > nums2.get(p2)) {
                p2++;
                lastestmove=2;
            }else if (p2 == (nums2.size() - 1)) {
                if(!oddnum){
                    if(!p1side&&nums2.get(p2)>=nums1.get(p1)){
                        p1++;
                        lastestmove=1;
                    }else if(!p1side&&nums2.get(p2)<nums1.get(p1)){
                        p1side=true;
                    }else{
                        p1++;
                        lastestmove=1;
                    }    
                }else{
                    if(!p1side&&nums2.get(p2)>nums1.get(p1)){
                        p1++;
                        lastestmove=1;
                    }else{
                        if(!p1side){
                            p1side=true;
                        }else{
                            p1++;
                            lastestmove=1;
                        }
                    }
                }
            }
            icounter--;
        }
        if (!oddnum) { //此时取中间两个值的平均数为中位数
            if(p1side){//中间两个数位于p1侧
                res=((double)(nums1.get(p1)) + (double)(nums1.get(p1+1))) / 2;
            }else if(p2side){//中间两个数位于p2侧
                res=((double)(nums2.get(p2)) + (double)(nums2.get(p2+1))) / 2;
            }else{
                double minright=(double)(nums2.get(p2));
                double minleft=(double)(nums1.get(p1));
                if(lastestmove==1){
                    //此时p1为左值
                    //偶数个数时,当最后一次移动发生在p1侧且p1侧没有到达末尾,比较p1+1和p2大小,取较小值作为右值
                    minleft=(double)(nums1.get(p1));
                    minright=nums1.get(p1+1)>nums2.get(p2)?nums2.get(p2):nums1.get(p1+1);
                }else if(lastestmove==2){
                    //此时p2为右值
                    //原理同上,比较p2+1和p1大小,取较小值
                    minleft=(double)(nums2.get(p2));
                    minright=nums2.get(p2+1)>nums1.get(p1)?nums1.get(p1):nums2.get(p2+1);
                }
                res=( minleft + minright) / 2;
            }
        } else { //此时取p1、p2两者较小的值
            if(p1side){
                res = nums1.get(p1);
            }else if(p2side){
                res = nums2.get(p2);
            }else{
                res = Math.min(nums2.get(p2),nums1.get(p1));
            }
        }
        return res;
    }
}

四、刷题链接

两个升序数组的中位数_牛客题霸_牛客网

五、近似题目

数组-在两个长度相等的有序数组中找到上中位数-CSDN博客文章浏览阅读272次,点赞4次,收藏6次。java刷题:查找两个长度相等的有序数组中的上中位数。https://blog.csdn.net/hehe_soft_engineer/article/details/139200124?spm=1001.2014.3001.5502

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/652072.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Google Extension 【Google 最佳扩展插件】

pockettube: youtube manager 订阅号分组沉浸式翻译&#xff1a;全网口碑炸裂的双语对照网页翻译插件Google 翻译腾讯翻译篡改猴MetaMaskGlarity: Summarize & Translate Any Page

移动端应用订阅SDK接入攻略

本文档介绍了联想应用联运移动端订阅SDK接入操作指南&#xff0c;您可在了解文档内容后&#xff0c;自行接入应用联运移动端订阅SDK。 接入前准备 1请先与联想商务达成合作意向。 2.联系联想运营&#xff0c;提供应用和公司信息&#xff0c;并获取商户id、app id、key&#…

卸载/删除 Maxask.com,最简单的方法

被绑架的浏览器&#xff0c;太恶心了。 Maxask伪装成了插件&#xff0c;在你搜索网页的时候利用了重定向&#xff0c;导致出现的界面时Maxask的界面&#xff0c;很恶心。 只需要排查正在使用的&#xff0c;如下图有颜色的图表。 删除一个插件&#xff0c;浏览器搜索一下看看有…

2024年上半年软件设计师试题及答案(回忆版)--选择题

基础知识选择题 基础知识选择题 1,2,3][4,5,6][1,2,3,4,5,6] &#xff08;总&#xff1a;1分&#xff09; &#xff08;注意&#xff1a;括号内的是截止当前题目总分&#xff09; vlan不能隔绝内外网 &#xff08;2分&#xff09; 链路层使用交换机&#xff0c;…

C语言 | Leetcode C语言题解之第115题不同的子序列

题目&#xff1a; 题解&#xff1a; int numDistinct(char* s, char* t) {int m strlen(s), n strlen(t);if (m < n) {return 0;}unsigned long long dp[m 1][n 1];memset(dp, 0, sizeof(dp));for (int i 0; i < m; i) {dp[i][n] 1;}for (int i m - 1; i > 0;…

M2m中的采样

采样的完整代码 import torch import numpy as np from torchvision import datasets, transforms from torch.utils.data import DataLoader, WeightedRandomSampler, SubsetRandomSamplerdef get_oversampled_data(dataset, num_sample_per_class):""" Gener…

Brewer Science将在CS Mantech进行展示

在风景如画的亚利桑那州图森市举办的CS Mantech盛会上&#xff08;2024年5月20日至23日&#xff09;&#xff0c;杰出化合物半导体材料企业Brewer Science&#xff0c;将带来一场名为“化合物半导体制造的创新材料解决方案”的演讲盛宴。这一演讲&#xff0c;定于五月二十一日星…

宝塔:如何在宝塔面板做301重定向

如何在宝塔面板做301重定向?301重定向对于网站来说非常重要。如果你的网站以www开头&#xff0c;我们应该把没有www的域名重定向到有www的域名&#xff0c;反之亦然。 1、我们进入宝塔管理后台 2、登录面板并单击添加站点。既然要把xxx.com 301发到www.xxx.com&#xff0c;我…

【设计模式深度剖析】【5】【结构型】【桥接模式】| 以电视和遥控器为例加深理解

&#x1f448;️上一篇:组合模式 设计模式-专栏&#x1f448;️ 目 录 桥接模式(Bridge Pattern)定义英文原话是&#xff1a;直译理解 4个角色UML类图代码示例 应用优点缺点使用场景 示例解析&#xff1a;电视和遥控器UML类图 桥接模式(Bridge Pattern) 定义 英文原话是&am…

最新!!2024年上半年软考【中级】网络工程师 综合知识真题解析

2024上半年软考考试已经结束了&#xff0c;为大家整理了网友回忆版的网络工程师真题及答案&#xff0c;总共41道题。 上半年考试的宝子们可以对答案预估分数&#xff01;准备下半年考的宝子可以提前把握考试知识点和出题方向&#xff0c;说不定会遇到相同考点的题目&#xff01…

基于ssm+vue图书管理系统

基于ssmvue图书管理系统 ssm477图书管理系统 相关技术 javassmmysqlvueelementui

上海亚商投顾:沪指震荡反弹 半导体产业链午后爆发

上海亚商投顾前言&#xff1a;无惧大盘涨跌&#xff0c;解密龙虎榜资金&#xff0c;跟踪一线游资和机构资金动向&#xff0c;识别短期热点和强势个股。 一.市场情绪 沪指昨日震荡反弹&#xff0c;尾盘涨幅扩大至1%&#xff0c;深成指、创业板指同步上行&#xff0c;科创50指数…

搭载昇腾310NPU的Orange Pi AIpro开箱体验以及深度学习样例测试

Orange Pi AIpro开箱体验以及样例测试 随着人工智能和物联网技术的快速发展&#xff0c;单板计算机&#xff08;Single Board Computer, SBC&#xff09;在创客和开发者社区中越来越受到欢迎。我最近入手了一款高性能的单板计算机——Orange Pi AIpro。 在入手此款AI开发板之…

【三维重建】ePnP

PnP问题应用与一下场景&#xff1a; 已知三维点和对应二维点以及相机相机内参数&#xff0c;可以获取相机外参。 我们介绍其中的一种算法&#xff1a;ePnP 算法流程 1、ePnP算法首先在世界坐标系内寻找4个控制点&#xff0c;记作 C 1 w , C 2 w , C 3 w , C 4 w C_1^w,C_2^w,…

Laravel和ThinkPHP框架比较

一、开发体验与易用性比较 1. 代码可读性&#xff1a; - Laravel以其优雅的语法和良好的代码结构著称&#xff0c;使得代码更加易读易懂。 - 相比之下&#xff0c;ThinkPHP的代码可读性较为一般&#xff0c;在一些复杂业务场景下&#xff0c;可能会稍显混乱。 让您能够一站式…

每天写两道(一):无重复字符的最长子串、反转链表

3. 无重复字符的最长子串 3. 无重复字符的最长子串 给定一个字符串 s &#xff0c;请你找出其中不含有重复字符的 最长子串的长度。 输入: s "abcabcbb" 输出: 3 解释: 因为无重复字符的最长子串是 "abc"&#xff0c;所以其长度为 3。(1)滑动窗口 双…

Web安全:文件上传漏洞详解,文件上传漏洞原理、绕过方式和防御方案。

「作者简介」&#xff1a;2022年北京冬奥会网络安全中国代表队&#xff0c;CSDN Top100&#xff0c;就职奇安信多年&#xff0c;以实战工作为基础对安全知识体系进行总结与归纳&#xff0c;著作适用于快速入门的 《网络安全自学教程》&#xff0c;内容涵盖系统安全、信息收集等…

搭建服务器的主流中间件有哪些?如何在外网访问内网的服务?

计算机业内人士对于搭建服务器的中间件并不陌生&#xff0c;apache、tomcat、IIS、nginx 都是比较常用的搭建服务器的中间件&#xff0c;它们之间还是有一些区别差异的。今天就说说这些中间件之间有哪些区别&#xff0c;以及如何利用快解析实现内网主机应用让外网访问。 首先说…

c++ 将指针转换为 void* 后,转换为怎么判断原指针类型?

当将指针转换为void后&#xff0c;擦除了指针所指向对象的类型信息&#xff0c;因此无法通过void指针来判断原始指针的类型。我这里有一套编程入门教程&#xff0c;不仅包含了详细的视频讲解&#xff0c;项目实战。如果你渴望学习编程&#xff0c;不妨点个关注&#xff0c;给个…

【状态机动态规划】3129. 找出所有稳定的二进制数组 I

本文涉及知识点 动态规划汇总 LeetCode 3129. 找出所有稳定的二进制数组 I 给你 3 个正整数 zero &#xff0c;one 和 limit 。 一个 二进制数组 arr 如果满足以下条件&#xff0c;那么我们称它是 稳定的 &#xff1a; 0 在 arr 中出现次数 恰好 为 zero 。 1 在 arr 中出现…