简体   繁体   中英

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. 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 .

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).

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 .

and maximum value of an element in an array is 10^5

This makes it trivial. Use boolean[10001] and mark all multiples of all queries. 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 . Now the worst case is {1, 2, 3, 4, ...} , which needs 10001/1 + 10001/2 + 10001/3... steps. 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. 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. 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. Memory complexity would be the same.

Then you can answer your queries in O(1) by a lookup in the table.

You can check this link for how to generate divisors in O(sqrt(V)) .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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