博客
关于我
找中位数
阅读量:656 次
发布时间:2019-03-15

本文共 2451 字,大约阅读时间需要 8 分钟。

设计一个算法快速计算无序数列的中位数,时间复杂度为O(n)。

中位数的定义为:若数列元素个数为奇数,则为排序后中间的数;若为偶数,则为中间两个数的平均值。常规排序方法时间复杂度为O(n log n),但我们需要线性时间解决方案。快速选择算法(Quick Select)可满足这一需求,因为其平均时间复杂度为O(n)。

实现思路

  • 快速选择算法

    • 递归地选择数组中的基准元素,调整范围,直到找到精确的中位数位置。
    • 对于奇数个元素,找到中间的那个元素;对偶数个元素,分别找到中间两个元素的位置。
  • 平衡性考虑

    • 基准的选取策略直接影响算法的效率,选择中间位置的基准减少递归深度,确保O(n)时间复杂度。
  • 处理边界情况

    • 基准选取后,根据基准分割数组,确定下一步查找的方向。
    • 处理分割线等于当前基准时的特殊情况。
  • 代码实现

    import java.util.Scanner;public class zhongweishu {    public static void main(String[] args) {        Scanner sc = new Scanner(System.in);        while (sc.hasNext()) {            int n = sc.nextInt();            int[] a = new int[n];            for (int i = 0; i < n; i++) {                a[i] = sc.nextInt();            }            if (n % 2 != 0) {                int p = quickSelect(a, 0, n - 1, (n + 1) / 2);                System.out.println(p);            } else {                int mid1 = quickSelect(a, 0, n - 1, n / 2);                int mid2 = quickSelect(a, 0, n - 1, n / 2 + 1);                double avg = (mid1 + mid2) / 2.0;                System.out.printf("%.3f", avg);            }        }    }    private static int quickSelect(int[] a, int left, int right, int k) {        if (left == right) {            return a[left];        }        int pivot = ((new Random()).nextInt(right - left + 1) + left);        int temp = a[pivot];        a[pivot] = a[left];        a[left] = temp;        int i = left + 1;        int j = right;        while (i < j) {            if (a[i] > a[j]) {                if (i != left + 1) {                    a[pivot] = a[i];                    a[i] = a[left];                    a[left] = a[right];                    a[right] = a[pivot];                    pivot = left;                }                a[right] = a[j];                a[j] = a[right];                j--;            } else {                if (j != right) {                    a[pivot] = a[j];                    a[j] = a[right];                    a[right] = a[pivot];                    pivot = right;                }                a[right] = a[i];                a[i] = a[right];                i++;            }        }        if (pivot < k) {            return quickSelect(a, pivot + 1, right, k);        } else {            return quickSelect(a, left, pivot - 1, k);        }    }}

    代码解释

    • 主函数:读取输入,调用快速选择函数找到中位数,输出结果。
    • 快速选择函数:使用中间点的随机选择作为基准,将数组分割为三部分。根据基准位置,确定下一步查找范围。
    • 分割策略:基准随机选取,通过交换元素位置,并调整查找范围,确保每次查找范围减少。

    这种方法确保了在线性时间内找到数列的中位数,适用于大规模数据处理。通过合理的分割策略,算法在各个情况下均能有效运行。

    转载地址:http://nmkqz.baihongyu.com/

    你可能感兴趣的文章
    Vue.js学习-15-v-for循环数组内容
    查看>>
    研发效能工具集
    查看>>
    saas创业八阶段-4、团队复制阶段
    查看>>
    【AI全栈二】视频流多目标多类别无延迟高精度高召回目标追踪 YOLO+Deepsort 全解
    查看>>
    2020 祥云杯misc 到点了
    查看>>
    Linux——系统安全及应用(开关机安全机制、系统弱口令检测、NMAP)
    查看>>
    C语言共用体union
    查看>>
    kafka超时错误或者发送消息失败等错误,排错方式
    查看>>
    Python3 排序函数问题
    查看>>
    Python3 多线程问题
    查看>>
    Windows下配置单机Hadoop环境 pyspark
    查看>>
    git教程之远程仓库
    查看>>
    程序员搞笑动图:告诉你真正的人工智能什么鬼 区块链
    查看>>
    Android Unable to find explicit activity class问题
    查看>>
    Vue路由跳转如何传递一个对象过去?
    查看>>
    sockjs-node/info?t=1462183700002 报错解决方案
    查看>>
    解决VS Code保存时候自动格式化
    查看>>
    FI 替代相关 OSS Note 要点记录
    查看>>
    Problem E: Print Graphics Problerm (IV) (Append Code)
    查看>>
    Problem K: 三角形数
    查看>>