计算数组的最大长度,使得平均值小于给定值

Posted

技术标签:

【中文标题】计算数组的最大长度,使得平均值小于给定值【英文标题】:calculate the max length of an array such that average is less than given value 【发布时间】:2018-08-19 14:30:57 【问题描述】:

我一直在尝试解决这个问题,但大多数测试用例都超时了。谁能帮我优化这个?

问题陈述:

给定一个长度为 N 的数组 A。你必须从给定的数组 A 中选择一个子集 S,使得 S 的平均值小于 K。你需要打印 S 的最大可能长度。

输入格式:

The first line of each input contains  N, length of array A.
Next line contains N space separated elements of array A.
Next line of input contains an integer Q, Number of queries.
Each following Q  lines contains a single integer K.

输出格式:

For each query, print single integer denoting the maximum possible length of the subset.

示例输入

5 1 2 3 4 5 5 1 2 3 4 5

样本输出

0 2 4 5 5

解释

    在第一个查询中,没有可能的子集使得其平均值小于 1。 在第二个查询中,您可以选择子集 1,2。 在第三个查询中,您可以选择子集 1,2,3,4。 在第四和第五个查询中,您可以看到完整的数组 1,2,3,4,5。

这是我的解决方案:

import java.util.*;

public class Playground 
    public static void main(String args[] ) throws Exception 
        Scanner s = new Scanner(System.in);
        long n = Long.parseLong(s.nextLine());                 // Reading input from STDIN
        String[] temp = s.nextLine().trim().split(" ");
        long[] arr = new long[(int) n];
        for (int i = 0; i < n; i++) 
            arr[i] = Integer.parseInt(temp[i]);
        long q = Long.parseLong(s.nextLine());

        long[] queries = new long[(int) q];
        for (int i = 0; i < q; i++) 
            long x = Long.parseLong(s.nextLine());
            queries[i] = x;
        
        PriorityQueue<Long> queue = new PriorityQueue<>();
        for (long x : arr)
            queue.add(x);
        for (long x : queries) 
            double avg = 0;
            List<Long> list = new ArrayList<>();
            int i = 0;
            int sum = 0;
            boolean flag = false;
            while (! queue.isEmpty()) 
                long num = queue.poll();
                i++;
                list.add(num);
                sum += num;
                avg = (double) sum / i;

                if (avg >= x) 
                    System.out.println(i - 1);
                    flag = true;
                    break;
                

            
            if (! flag)
                System.out.println(n);
            queue.addAll(list);
        
    

【问题讨论】:

好奇:如果您知道nq 需要适合int,为什么要使用parseLong 而不是parseInt 是的,你是对的。我们可以忽略它。 不要使用PriorityQueue,您必须不断重建。只需对数组进行一次排序,然后为每个查询重新使用它。 --- 另外,double 除法比long 乘法慢得多,所以if ((double) sum / i &gt;= x) 应该重写为if (sum &gt;= x * i)。 --- 不知道这两个提示是否会带来足够的性能提升,按时完成任务。你得试试看。 我从来没有看到从挑战站点中选择一个问题然后让其他人解决它的意义。我的问题,不是你的。 :-) 【参考方案1】:

解决这个问题的一个简单方法是先对数组进行排序。 在您对数组进行排序以使每个元素都等于或大于最后一个元素之后,解决单次运行很容易:

int count = 0;
int limit = 0;
for (int i : sortedArray) 
    int diff = i - maxAvg;
    if (limit + diff < 0) 
        limit += diff;
        count++
     else 
        break;
    

System.out.println(count);

这是可行的,因为如果与最大平均值的差为负,您可以使用具有正差的值,直到达到限制。

排序数组是O(n*log(n)),对于每个解决方案你只需要O(n)

这是我所有解析的完整解决方案:

public static void main(String[] args) 
    Scanner sc = new Scanner(System.in);
    int arrLen = Integer.parseInt(sc.nextLine());
    int[] array = new int[arrLen];
    String[] strNums = sc.nextLine().split(" ", arrLen);
    for (int i = 0; i < arrLen; i++) 
        array[i] = Integer.parseInt(strNums[i]);
    

    Arrays.sort(array);

    int numTests = Integer.parseInt(sc.nextLine());
    for (int i = 0; i < numTests; i++) 
        int maxAvg = Integer.parseInt(sc.nextLine());
        int limit = 0;
        int count = 0;
        for (int j : array) 
            int diff = j - maxAvg;
            if (limit + diff < 0) 
                count++;
                limit += diff;
             else 
                break;
            
        
        System.out.println(count);
    
    sc.close();

【讨论】:

只有低于平均水平的数字才能找到答案[1,2](平均=1.5)k=2 谢谢,我犯了一个小错误。但我不只是选择低于平均水平的数字。在您的示例中,在第一轮之后,limit-1(-1) + 0&lt; 0,所以也会被选中。

以上是关于计算数组的最大长度,使得平均值小于给定值的主要内容,如果未能解决你的问题,请参考以下文章

给定 n 个整数,找出平均数最大且长度为 k 的连续子数组,并输出该最大平均数

数组的平均值最大值最小值

最佳牛围栏

查找整数数组的平均值

C语言试题五之计算并输出给定数组(长度为9)中每相邻两个元素之平均值的平方根之和

813. 最大平均值和的分组(Python)