第3关:寻找两个等长有序序列的中位数

TOC寻找两个等长有序序列的中位数

对于一个长度为n的有序序列(假设均为升序序列)a0...n-1,处于中间位置的元素称为a的中位数。

设计一个算法求给定的两个有序序列的中位数。

例如,若序列a=(11,13,15,17,19),其中位数是15,若b=(2,4,6,8,20),其中位数为6。两个等长有序序列的中位数是含它们所有元素的有序序列的中位数,例如a、b两个有序序列的中位数为11。

任务描述

本关任务:编写一个能计算两个等长有序序列的中位数。

相关知识

如何求解?

对于含有n个元素的有序序列as...t,当n为奇数时,中位数是出现在m=(s+t)/2(下取整)处;当n为偶数时,中位数下标有m=(s+t)/2(下取整)(下中位)和m=(s+t)/2+1(上取整)(上中位)两个。为了简单,仅考虑中位数为m=(s+t)/2(下取整)处。

采用二分法求含有n个有序元素的序列a、b的中位数的过程如下:

(1)若n=1,较小者为中位数。

(2)其他又分为3种情况。

分别求出a、b的中位数am1和bm2:

  ① 若am1=bm2,则am1或bm2即为所求中位数,算法结束。

② 若am1<bm2,则舍弃序列a中前半部分(较小的一半),同时舍弃序列b中后半部分(较大的一半)要求舍弃的长度相等。

③ 若am1>bm2,则舍弃序列a中后半部分(较大的一半),同时舍弃序列b中前半部分(较小的一半),要求舍弃的长度相等。舍弃一半即n/2个元素。

编程要求

根据提示,在右侧编辑器补充代码,计算并输出两个等长有序序列的中位数。

测试说明

平台会对你编写的代码进行测试

测试输入:5

11,13,15,17,19

2,4,6,8,20

输出结果:

a:11 13 15

b:6 8 20

a:11 13

b:8 20

a:11

b:20

中位数:11

开始你的任务吧,祝你成功!

java 复制代码
import java.util.Scanner; // 导入Scanner类用于输入
import java.util.Arrays; // 导入Arrays类用于数组操作

/**
 * @author hainingLi
 */
public class MinNUMBER {
    /begin
    // 定义方法用于查找两个已排序数组的中位数
    // 定义的数组,中位数,查找中位数
    public static int findMedianSortedArrays(int[] a, int[] b) {  // 定义的一个findMedian, 数组排序的方法。分别传三叔 数组,对数组啊,和b 进行操作。

        while (a.length > 1 && b.length > 1) { // 当两个数组长度都大于1时循环
            int amid = a[a.length / 2]; // 获取数组a的中位数   ,a[a.length/2]
            int bmid = b[b.length / 2]; // 获取数组b的中位数

            // 特殊情况处理:数组长度为2时直接取第一个元素
            if (a.length == 2) {  // 如果a.length 的长度为2
                amid = a[0];  // 数组的第一个元素就是中位数
                bmid = b[0]; // 数组第一个元素就是中位数
            }

            // 根据中位数大小决定如何切分数组   // 根据中位数的大小决定如何切分数组

            if (amid < bmid) {    // 如果第一个数组的中位数小于第二个数组的中位数

                a = Arrays.copyOfRange(a, a.length / 2, a.length); // 将a数组切分为后半部分
                b = Arrays.copyOf(b, (b.length + 1) / 2); // 将b数组切分为前半部分

                // 打印当前数组状态  // 打印当前数组的状态
                System.out.print("a:");
                for (int i = 0; i < a.length; i++) {
                    System.out.print(a[i] + " "); // 打印数组a的当前状态
                }
                System.out.println(); // 换行

                System.out.print("b:");
                for (int i = 0; i < b.length; i++) {   // 遍历第二个数组
                    System.out.print(b[i] + " "); // 打印数组b的当前状态
                }
                System.out.println(); // 换行
            } else {
                b = Arrays.copyOfRange(b, b.length / 2, b.length); // 将b数组切分为后半部分
                a = Arrays.copyOf(a, (a.length + 1) / 2); // 将a数组切分为前半部分

                // 打印当前数组状态
                System.out.print("a:");
                for (int i = 0; i < a.length; i++) {
                    System.out.print(a[i] + " "); // 打印数组a的当前状态
                }
                System.out.println(); // 换行

                System.out.print("b:");
                for (int i = 0; i < b.length; i++) {
                    System.out.print(b[i] + " "); // 打印数组b的当前状态
                }
                System.out.println(); // 换行
            }
        }

        // 当其中一个数组为空时,返回非空数组的第一个元素作为中位数
        if (a.length == 0) {
            return b[0];
        }
        if (b.length == 0) {
            return a[0];
        }

        // 返回两数组首元素中较小的那个作为中位数
        return Math.min(a[0], b[0]);   // 返回两个数组元素中较小的那个作为中位数
        
    }

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in); // 创建Scanner对象用于读取输入
        // 读取输入的数组长度
        int n = scanner.nextInt();  // 输入的随机数n
        scanner.nextLine(); // 读取换行符
        // 读取第一个数组的元素
        String[] aInput = scanner.nextLine().split("\\s+");  // 随机数组,第一个
        int[] a = new int[aInput.length]; //  循环第一个数组元素 放到新的额数组a中
        for (int i = 0; i < n; i++) { // 遍历这个随机输入的这个n 数
            a[i] = Integer.parseInt(aInput[i].trim()); // 将字符串转换为整数
        }
        // 读取第二个数组的元素
        String[] bInput = scanner.nextLine().split("\\s+");
        int[] b = new int[bInput.length];
        for (int i = 0; i < n; i++) {
            b[i] = Integer.parseInt(bInput[i].trim()); // 将字符串转换为整数
        }
        // 对输入的数组进行排序
        Arrays.sort(a);
        Arrays.sort(b);
        // 计算并输出中位数
        int median = findMedianSortedArrays(a, b); // 调用方法计算中位数    这个中位数是两个数组中较小的中位数
        System.out.print("中位数:" + median); // 输出中位数
        // 关闭scanner以释放资源
        scanner.close();
    }
}
相关推荐
_Evan_Yao7 小时前
Redis 缓存穿透、击穿、雪崩,一次讲清!
java·spring·mybatis
梓豪csd7 小时前
消息订阅中心:谁该收到哪条通知
java·开发语言·人工智能·低代码·自动化·1024程序员节
秋饼7 小时前
Spring AI 2.1 Message Parts 深度实战:推理签名回放与跨轮记忆持久化的源码级落地
java·ai·技术分享·后端开发
thefool1122668 小时前
TCP 1
java·1024程序员节
企业数字化笔记10 小时前
视频人体姿态怎么做三维可视化?2D关键点、深度局限与技术选型
人工智能·算法·音视频
金銀銅鐵10 小时前
[Java] 用 GUI 展示 EnumSet 增减元素时的内部变化(下)
java·后端·ai编程
?abc!11 小时前
(数组)581. 最短无序连续子数组
数据结构·算法·leetcode
AI人工智能+电脑小能手11 小时前
一次请求打几个下游,这个Java并行任务工具类6个方法按序聚合
java·线程池·并发编程·1024程序员节·批量处理·并行任务
paopaokaka_luck12 小时前
心理咨询管理系统(WebSocket实时沟通、基于用户的协同过滤、 ECharts多维分析、 预约业务流程、预约校验与定时处理)
java·vue.js·spring boot·mysql·spring·echarts·1024程序员节
2301_322414280413 小时前
springboot农产品交易平台的设计与实现08055-计算机毕设 原创(免费领源码+部署教程+开发环境)
java·spring boot·redis·mysql·tomcat·maven·mybatis