简体   繁体   English

计算可被给定查询 k 整除的数组中的整数数

[英]Count the number of integers in an array divisible by a given query k

In this problem I have a number of queries for which I have to output the count of integers in the array which is divisible by k(one of the queries).The array contains duplicate elements.在这个问题中,我有许多查询,我必须输出arrayintegers的计数,该array可被 k(查询之一)整除。该array包含重复元素。 I am trying to optimise the problem and my approach is given below :我正在尝试优化问题,我的方法如下:

Code:代码:

public static void main(String[] args) {
    Scanner sc=new Scanner(System.in);
     int[] ar={2,4,6,9,11,34,654,23,32,54,76,21432,32543,435,43543,643,2646,4567,457654,75,754,7,567865,8765877,53,2};
     int query=sc.nextInt();
     int length=ar.length;
     int count=0;
     for (int i=0;i<query ;i++ ) {
        int x=sc.nextInt();
        for (int j=0;j<length ;j++ ) {
            if(ar[j]>x){
                if(ar[j]%x==0){
                    count++;
                }
            }
        }
        System.out.println("Count:"+count);
     }
}

The above code gives the correct output, but the complexity is O(query*length) and what if the array size is much bigger,the program will timeout .上面的代码给出了正确的输出,但复杂度是O(query*length)并且如果数组大小大得多,程序会timeout

Can anyone help me optimize the problem?谁能帮我优化问题?

One optimization that you could do is to take advantage of short-circuiting , and use one if statement (instead of two).您可以做的一种优化是利用短路,并使用一个 if 语句(而不是两个)。

So change this:所以改变这个:

if(ar[j]>x) {
  if(ar[j]%x==0) {

to this:对此:

if(ar[j]>x && ar[j]%x==0) {

This will not affect the time complexity of your algorithm, but it will help Branch Prediction .这不会影响算法的时间复杂度,但会有助于Branch Prediction

and maximum value of an element in an array is 10^5数组中元素的最大值为 10^5

This makes it trivial.这使它变得微不足道。 Use boolean[10001] and mark all multiples of all queries.使用boolean[10001]并标记所有查询的所有倍数。 Then use it for testing the elements.然后用它来测试元素。

The new problem is how to mark all the multiples when there are many small queries.新的问题是当有很多小查询时如何标记所有的倍数。 The worst case would be queries like {1, 1, 1, ...} , but duplicates can be trivial removed eg, using a HashSet .最坏的情况是像{1, 1, 1, ...}这样的查询,但可以简单地删除重复项,例如,使用HashSet Now the worst case is {1, 2, 3, 4, ...} , which needs 10001/1 + 10001/2 + 10001/3... steps.现在最坏的情况是{1, 2, 3, 4, ...} ,它需要10001/1 + 10001/2 + 10001/3...步骤。 You can do some special treatment for the smallest queries like removing multiples.您可以对最小的查询进行一些特殊处理,例如删除倍数。

For example, when you look at all queries up to 10 and remove multiples among them, then the worst case is {2, 3, 5, 7, 11, 12, 13, 14...} , which should make the marking pretty fast.例如,当您查看最多 10 个查询并删除其中的多个查询时,最坏的情况是{2, 3, 5, 7, 11, 12, 13, 14...} ,这应该使标记漂亮快速地。 This step may not be needed at all.这一步可能根本不需要。

You can do a precomputation step to build a divisors' table.您可以执行预计算步骤来构建除数表。 For every element in the array calculate its divisors.对于数组中的每个元素,计算其除数。 You can calculate divisors of a number efficiently in O(sqrt(V)) assuming V is the maximum value in the array.假设V是数组中的最大值,您可以在O(sqrt(V))有效地计算一个数字的除数。 Building the full table will cost O(n * sqrt(V)) which according to your constraints equals 100,000 * sqrt(100,000) =~ 32M which shouldn't be a lot.构建完整表将花费O(n * sqrt(V))根据您的约束等于100,000 * sqrt(100,000) =~ 32M ,这应该不会很多。 Memory complexity would be the same.内存复杂度是一样的。

Then you can answer your queries in O(1) by a lookup in the table.然后您可以通过在表中查找来回答O(1)的查询。

You can check this link for how to generate divisors in O(sqrt(V)) .您可以查看此链接以了解如何在O(sqrt(V))生成除数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM