每日一题——插入排序实现数据流中的中位数

插入排序实现数据流中的中位数

题目描述

设计一个算法,用来计算数据流中的中位数。当数据流中读出奇数个数值时,中位数就是所有数值排序之后位于中间的数值;当数据流中读出偶数个数值时,中位数就是所有数值排序之后中间两个数的平均值。

功能要求

  • Insert(num):从数据流中读取一个整数,并将其插入到有序数组中
  • GetMedian():返回当前读取数据的中位数

数据范围

  • 数组大小限制:1000
  • 确保数据流中所有整数都在 int 范围内

解题思路

本题采用有序数组的方式实现,主要思路如下:

  1. 使用一个全局数组保存所有数据
  2. 每次插入时保持数组有序
  3. 根据数组长度的奇偶性计算中位数

算法流程

  1. 插入数据时,先将数据加入数组末尾
  2. 通过插入排序的方式维护数组有序性
  3. 获取中位数时,根据数组长度判断返回中间位置或中间两个数的平均值

代码实现

c 复制代码
/**
 * 全局变量声明区
 */
#include <math.h>

// 定义一个固定大小的数组来存储数据流中的数字
int arr[1000];

// 定义top指针,初始化为-1表示空数组
// top表示当前数组中最后一个元素的索引
int top = -1;

/**
 * Insert函数:将新的数字插入到数组中,并保持数组有序
 * @param num: 要插入的新数字
 * @return: 无返回值
 * 算法思路:使用插入排序的思想,每次插入后保持数组有序
 */
void Insert(int num) {
    // 先将新数字插入到数组末尾
    // ++top先自增再使用,所以先给top加1,再在新位置存入数字
    arr[++top] = num;
    
    // 使用插入排序的思想,将新插入的数字调整到正确的位置
    // i>0确保不会数组越界
    // arr[i]<arr[i-1]判断当前数字是否小于前一个数字
    for(int i = top; i > 0 && arr[i] < arr[i-1]; i--) {
        // 如果当前数字小于前一个数字,则交换它们的位置
        int temp = arr[i];        // 暂存当前数字
        arr[i] = arr[i-1];        // 将前一个数字后移
        arr[i-1] = temp;          // 将当前数字放到前一个位置
    }
    
    // 打印当前插入的结果
    // top表示当前位置,arr[top]表示当前位置的数字
    printf("arr%d=%d", top, arr[top]);
}

/**
 * GetMedian函数:计算当前数组中所有数字的中位数
 * @param: 无参数
 * @return: 返回中位数,double类型
 * 算法思路:根据数组长度的奇偶性来决定返回中间一个数还是中间两个数的平均值
 */
double GetMedian() {
    // 通过判断top的奇偶性来确定数组长度的奇偶性
    // top是索引,所以实际长度是top+1
    if(top % 2 == 0) {
        // 如果top是偶数,说明数组长度是奇数
        // 直接返回中间位置的数字
        // 需要转换为double类型以确保精确度
        return (double)arr[top/2];
    } else {
        // 如果top是奇数,说明数组长度是偶数
        // 返回中间两个数字的平均值
        // 使用2.0来进行浮点数除法,确保结果的精确度
        return (arr[top/2] + arr[top/2+1]) / 2.0;
    }
}

代码详解

1. 全局变量

c 复制代码
int arr[1000];  // 存储数据的数组
int top = -1;   // 数组当前末尾索引
  • arr:用于存储所有插入的数据
  • top:记录当前数组最后一个元素的索引,初始为-1表示空数组

2. Insert 函数

c 复制代码
void Insert(int num) {
    arr[++top] = num;
    
    for(int i = top; i > 0 && arr[i] < arr[i-1]; i--) {
        int temp = arr[i];
        arr[i] = arr[i-1];
        arr[i-1] = temp;
    }
    
    printf("arr%d=%d", top, arr[top]);
}

关键点解析:

  • 先将新数据加入数组末尾
  • 使用插入排序方法,将新插入的数据调整到正确位置
  • 打印输出当前插入的数据及其位置

3. GetMedian 函数

c 复制代码
double GetMedian() {
    if(top % 2 == 0)
        return (double)arr[top/2];
    else
        return (arr[top/2] + arr[top/2+1]) / 2.0;
}

关键点解析:

  • 通过判断top的奇偶性确定当前数组长度的奇偶性
  • 奇数个元素时返回中间位置的元素
  • 偶数个元素时返回中间两个数的平均值
  • 使用2.0确保进行浮点数除法

复杂度分析

Insert 函数

  • 时间复杂度:O(n),其中n为当前数组长度
  • 空间复杂度:O(1),只需要常数级别的额外空间

GetMedian 函数

  • 时间复杂度:O(1),直接访问数组元素
  • 空间复杂度:O(1)

空间复杂度(整体)

  • O(n),需要一个数组存储所有数据

注意事项

  1. 数组大小限制

    • 需要确保不会超过1000个元素
    • 实际应用中应考虑动态扩容
  2. 数值范围

    • 确保输入的整数在int范围内
    • 计算平均值时注意使用double避免精度损失
  3. 边界条件

    • 处理第一个数据时的特殊情况
    • 注意数组索引不要越界,基本上只要注意边界问题,插入排序整体上还是非常容易的
相关推荐
思麟呀14 分钟前
栈和队列的实现(C语言)
c语言·数据结构·学习
byte轻骑兵25 分钟前
嵌入式C语言:大小端详解
c语言·开发语言·嵌入式软件开发
怎么这么多名字都被占了38 分钟前
llama.cpp的C语言API使用
c语言·人工智能·llama
中东大鹅43 分钟前
【排序算法】选择排序
数据结构·算法·排序算法
阿巴~阿巴~1 小时前
初识C语言、C语言的学习方向总述与入门
c语言·开发语言
Power++1 小时前
【BUUCTF逆向题】[2019红帽杯]easyRE
c语言·c++·python·网络安全·系统安全·密码学
九亿AI算法优化工作室&1 小时前
【SOC估计】基于扩展卡尔曼滤波器实现锂离子电池充电状态估计matlab代码和报告
开发语言·人工智能·算法·matlab·数据挖掘·回归
皎味小行家2 小时前
第四十六天|动态规划|子序列|647. 回文子串,5.最长回文子串, 516.最长回文子序列,动态规划总结篇
java·数据结构·算法·leetcode·动态规划
中东大鹅2 小时前
【排序算法】桶排序
算法·排序算法
E_han2 小时前
7.list
开发语言·汇编·数据结构·c++·算法·list