问题描述
西瓜视频正在开发一个新功能,旨在将访问量达到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%的数据的最大值。
解题思路
-
输入解析:
- 将输入字符串中的数据转换为一个整数数组。
-
数据排序:
- 将数组按照升序排序,方便找到具体百分位数的位置。
-
计算位置:
- 百分位数的位置是 位置 = ⌈N · 0.8⌉ ,需要考虑到数组索引从0开始,最终位置为 位置 - 1。
-
提取结果:
- 根据计算得到的索引,返回对应位置的数值。
代码实现
以下是完整的代码实现,包含测试样例:
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, 2, 3, 4, 5, 6, 7, 8, 9, 10] - 位置 = ⌈N · 0.8⌉ (索引为7)
- 输出:
8
样例2:
输入: data = "1,0,8,7,3,9,12,6,4,15,17,2,14,5,10,11,19,13,16,18"
步骤:
- 排序后:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19] - 位置 = ⌈20 · 0.8⌉ = 16 (索引为15)
- 输出:
15
时间复杂度
- 排序: O(n \log n)
- 查找索引: O(1)
总体时间复杂度为 O(n \log n)。