豆包MarsCode AI刷题(三)

46 阅读5分钟

今天给大家分享一下每日刷题的题目解析和经验分享,本系列预计会推出五期,今天给大家带来的是第三期的分享。

视频推荐的算法

问题描述

西瓜视频正在开发一个新功能,旨在将访问量达到80百分位数以上的视频展示在首页的推荐列表中。实现一个程序,计算给定数据中的80百分位数。

例如:假设有一个包含从1到100的整数数组,80百分位数的值为80,因为按升序排列后,第80%位置的数字就是80。

99 百分位数:假如有 N 个数据,将数据从小到大排列,99 百分位数是第 N99%位置处的数据(遇到小数时四舍五入获取整数)。一般计算逻辑是先排序,定位到 N99%的位置。返回该位置处的数据。同理,80 百分位数就是第 N*80%位置处的数据。


测试样例

样例1:

输入:data = "10,1,9,2,8,3,7,4,6,5"
输出:8

样例2:

输入:data = "1,0,8,7,3,9,12,6,4,15,17,2,14,5,10,11,19,13,16,18"
输出:15

样例3:

输入:data = "5,3,9,1,7"
输出:7

解决方案

要解决这个问题,我们需要计算给定数据中的80百分位数。

  1. 理解百分位数

    • 百分位数是指在一个数据集中,某个百分比位置的数值。例如,80百分位数是指在排序后的数据中,80%位置的数值。
    • 具体来说,如果数据集有N个元素,80百分位数就是第 N * 0.8 位置的元素。如果 N * 0.8 不是整数,则需要四舍五入到最近的整数。
  2. 数据处理

    • 输入数据是一个字符串,表示一组数字,数字之间用逗号分隔。
    • 首先需要将字符串解析为整数数组。
  3. 排序

    • 将解析后的整数数组按升序排序。
  4. 计算位置

    • 计算80百分位数的位置:int position = (int) Math.round(data.length * 0.8);
    • 注意:数组索引从0开始,所以实际的索引位置是 position - 1
  5. 返回结果

    • 返回排序后数组中对应位置的数值。
public class Main {
    public static int solution(String data) {
        // 1. 将输入的字符串解析为整数数组
        String[] parts = data.split(",");
        int[] numbers = new int[parts.length];
        for (int i = 0; i < parts.length; i++) {
            numbers[i] = Integer.parseInt(parts[i]);
        }

        // 2. 对整数数组进行排序
        Arrays.sort(numbers);

        // 3. 计算80百分位数的位置
        int position = (int) Math.round(numbers.length * 0.8);

        // 4. 返回排序后数组中对应位置的数值
        // 注意:数组索引从0开始,所以实际的索引位置是 position - 1
        return numbers[position - 1];
    }

    public static void main(String[] args) {
        //  测试代码如下
        System.out.println(solution("10,1,9,2,8,3,7,4,6,5") == 8);
        System.out.println(solution("1,0,8,7,3,9,12,6,4,15,17,2,14,5,10,11,19,13,16,18") == 15);
        System.out.println(solution("76,100,5,99,16,45,18,3,81,65,102,98,36,4,2,7,22,66,112,97,68,82,37,90,61,73,107,104,79,14,52,83,27,35,93,21,118,120,33,6,19,85,49,44,69,53,67,110,47,91,17,55,80,78,119,15,11,70,103,32,9,40,114,26,25,87,74,1,30,54,38,50,8,34,28,20,24,105,106,31,92,59,116,42,111,57,95,115,96,108,10,89,23,62,29,109,56,58,63,41,77,84,64,75,72,117,101,60,48,94,46,39,43,88,12,113,13,51,86,71") == 96);
    }
}

复杂度分析

时间复杂度

  1. 解析字符串并转换为整数数组

    • data.split(","):分割字符串的时间复杂度为 O(n),其中 n 是字符串的长度。
    • Integer.parseInt(parts[i]):遍历字符串数组并转换为整数的时间复杂度为 O(m),其中 m 是数组的长度。
    • 因此,这一步的总时间复杂度为 O(n + m)。
  2. 排序整数数组

    • Arrays.sort(numbers):Java 的 Arrays.sort() 方法使用的是优化的快速排序或归并排序,平均时间复杂度为 O(m log m)。
  3. 计算80百分位数的位置

    • Math.round(numbers.length * 0.8):计算位置的时间复杂度为 O(1)。
  4. 返回结果

    • return numbers[position - 1]:访问数组元素的时间复杂度为 O(1)。

综合以上步骤,主要的时间复杂度来自于排序操作,因此总的时间复杂度为 O(mlogm)O(mlogm)

空间复杂度

  1. 解析字符串并转换为整数数组

    • String[] parts = data.split(","):需要额外的空间存储分割后的字符串数组,空间复杂度为 O(m)。
    • int[] numbers = new int[parts.length]:需要额外的空间存储整数数组,空间复杂度为 O(m)。
  2. 排序整数数组

    • Arrays.sort(numbers):排序操作本身不需要额外的空间,但快速排序或归并排序可能会使用一些辅助空间,最坏情况下为 O(m)。
  3. 计算80百分位数的位置

    • Math.round(numbers.length * 0.8):计算位置不需要额外的空间,空间复杂度为 O(1)。
  4. 返回结果

    • return numbers[position - 1]:访问数组元素不需要额外的空间,空间复杂度为 O(1)。

综合以上步骤,主要的空间复杂度来自于存储整数数组和分割后的字符串数组,因此总的空间复杂度为 O(m)。

总结

  • 时间复杂度:O(mlogm)
  • 空间复杂度:O(m)

其中,m 是输入字符串中数字的数量。