题目描述:
小U手里有一个由N个正整数组成的数组。她希望能够从中找到一个子序列,使得这个子序列的平均数大于一个给定的值K。你的任务是帮助小U找到这样的子序列,并且求出其中最长的子序列长度。如果无法找到平均数大于K的子序列,那么输出-1。
例如:给定数组为 [3, 1, 1, 2, 3],并且K=2。你可以选择子序列 [3, 1, 2, 3],此时它的平均数为2.25,大于K,并且这是最长的满足条件的子序列。
测试样例:
样例1: 输入:n = 5 , k = 2 , a = [3, 1, 1, 2, 3] 输出:4
样例2: 输入:n = 3 , k = 5 , a = [1, 2, 3] 输出:0
样例3: 输入:n = 6 , k = 3 , a = [6, 5, 2, 7, 8, 9] 输出:6
解析思路与实现细节
-
排序数组: 使用
Arrays.sort(a)
对输入数组进行升序排列。这一步骤是为了后续操作提供便利,因为有序数组有助于快速定位可能符合要求的子序列。 -
检查最大值: 判断数组中的最大值是否小于或等于
k
。如果是,则意味着整个数组都不可能形成平均数大于k
的子序列,因此直接返回0。 -
反向迭代计算: 从数组的最大值开始(即从数组的最后一个元素)向前迭代至第一个元素。对于每个元素,执行以下逻辑:
- 计算包含该元素在内的子序列的平均值 (
tmp
)。 - 检查此平均值是否小于
k
。如果小于k
,则表明已经找到一个平均数大于k
的子序列,返回当前已考虑的元素数量作为结果。 - 否则,累加当前元素值到总和(
res
),并将计数器(num
)增加1,以准备下一次循环。
- 计算包含该元素在内的子序列的平均值 (
-
返回结果: 如果循环结束仍未找到符合条件的子序列,则返回当前已考虑的元素总数。
算法核心思想
这种解法的核心在于利用数组排序后的特性,从大到小尝试构建子序列,从而避免了需要维护多个状态的复杂性。它巧妙地利用了数组排序后的单调递减性质,仅需单次线性扫描即可确定答案。
import java.util.Arrays;
public class Main {
public static int solution(int n, int k, int[] a) {
Arrays.sort(a); // Sort the array in ascending order.
float res = 0; // Initialize sum of elements considered so far.
float num = 0; // Initialize count of elements considered so far.
// Check if the maximum value is less than or equal to k.
if (a[a.length - 1] <= k) return 0;
// Iterate from the end of the sorted array towards the beginning.
for (int right = a.length - 1; right >= 0; right--) {
float tmp = (res + a[right]) / (num + 1); // Calculate average with current element included.
// If the calculated average is less than k, we found our sequence.
if (tmp < k) return (int) num;
// Otherwise, add this element's value and increment the count.
res += a[right];
num++;
}
// Return the total number of elements considered as the result.
return (int) num;
}
public static void main(String[] args) {
System.out.println(solution(5, 2, new int[]{3, 1, 1, 2, 3}) == 4);
System.out.println(solution(3, 5, new int[]{1, 2, 3}) == 0);
System.out.println(solution(6, 3, new int[]{6, 5, 2, 7, 8, 9}) == 6);
}
}
这段代码的关键点在于把子序列灵活转化为一个被排序后的数组,并基于当前子序列的平均值决定何时停止搜索。这种方法不仅简洁而且效率高,因为它只需要O(n log n)的时间复杂度(主要来自于排序),而空间复杂度则是O(1),不依赖于额外的数据结构。