视频推荐的算法题目解析 | 豆包MarsCode AI 刷题

92 阅读4分钟

问题描述

西瓜视频正在开发一个新功能,旨在将访问量达到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百分位数,也即按升序排列后,第 ⌈N · 0.8⌉ 个数据的位置处的值。百分位数常用于分析数据分布,在排序后的数组中,80百分位数是数组前80%的数据的最大值。

解题思路

  1. 输入解析:

    • 将输入字符串中的数据转换为一个整数数组。
  2. 数据排序:

    • 将数组按照升序排序,方便找到具体百分位数的位置。
  3. 计算位置:

    • 百分位数的位置是 位置 = ⌈N · 0.8⌉ ,需要考虑到数组索引从0开始,最终位置为 位置 - 1。
  4. 提取结果:

    • 根据计算得到的索引,返回对应位置的数值。

代码实现

以下是完整的代码实现,包含测试样例:

import java.util.Arrays;

public class Main {

    public static int solution(String data) {
        // 1. 解析输入字符串为整数数组
        String[] stringArray = data.split(",");
        int[] numbers = new int[stringArray.length];

        for (int i = 0; i < stringArray.length; i++) {
            numbers[i] = Integer.parseInt(stringArray[i].trim());
        }

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

        // 3. 计算80百分位数的位置(1-based索引)
        int n = numbers.length;
        int index = (int) Math.ceil(n * 0.8) - 1; // 转换为0-based索引

        return numbers[index];
    }

    public static void main(String[] args) {
        System.out.println(solution("10,1,9,2,8,3,7,4,6,5")); 
        System.out.println(solution("1,0,8,7,3,9,12,6,4,15,17,2,14,5,10,11,19,13,16,18")); 
        System.out.println(solution("5,3,9,1,7")); 
        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"));
    }
}

详细解析

步骤1: 解析输入数据

String[] stringArray = data.split(",");
int[] numbers = new int[stringArray.length];

for (int i = 0; i < stringArray.length; i++) {
    numbers[i] = Integer.parseInt(stringArray[i].trim());
}

将逗号分隔的字符串转换为整数数组,通过 Integer.parseInt 解析每个元素。


步骤2: 排序

Arrays.sort(numbers);

调用 Arrays.sort 对数组进行升序排序。


步骤3: 计算百分位数索引

int index = (int) Math.ceil(n * 0.8) - 1;
  • 使用 Math.ceil 计算位置,确保结果向上取整。
  • 转换为0-based索引时需减去1。

步骤4: 返回结果

return numbers[index];

通过排序后的数组直接返回对应位置的值。


测试样例解析

样例1:

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

步骤:

  1. 排序后: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
  2. 位置 = ⌈N · 0.8⌉ (索引为7)
  3. 输出: 8

样例2:

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

步骤:

  1. 排序后: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
  2. 位置 = ⌈20 · 0.8⌉ = 16 (索引为15)
  3. 输出: 15

时间复杂度

  1. 排序: O(n \log n)
  2. 查找索引: O(1)

总体时间复杂度为 O(n \log n)。