Problem Statement: You are given an array/sequence of positive numbers $a_1,a_2,a_3,\cdots,a_n$ and you need to execute q
queries on the array and in each query you will take a positive number as an input and find out all the multiples of the number in the given array and print it.
Input:
2 4 9 15 21 20
q1 = 2
q2 = 3
q3 = 5
Output:
3
3
2
To solve this problem I thought of an algorithm which works as explained below:
Create an array name
freq_data[]
whose length will be equal to the maximum element of the array, and it stores the count of each and every number occurred in the input array.
For Example:array[] = {2, 4, 9, 15, 21, 20} max_element = 21 freq_data[] = {0,1,0,1,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,1,1}
Create an array name
multiples[]
whose length will also be equal to maximum element encountered in the array. This array will store all the multiples of the numbers between $[1,\text{maximum value}]$. Usingmultiples[]
array, I can answer the query in $O(1)$ time by printing the value atmultiples[q - 1]
.Initialise the
multiples[0] = (size of arr[] - 1)
because every number in the array is divisible by 1.If the query entered is $(\gt \text{maximum value})$ in the array, then the answer will be zero because there will be no element in the array which will be divisible by
arr[i]
because for the number to be multiple of another, the number should be either equal to or greater than the divisor i.e $(\geq arr[i])$.Time Complexity: $O(max \times log(max))$
Space Complexity: $O(max)$
Now I was wondering what if I changed the question like instead of taking the queries from the user, I am now interested in finding for each arr[i]
how many multiples are present in the left-sub array with respect to arr[i]
.
Formally: You are given a sequence of positive numbers $a_1,a_2,a_3,\cdots,a_n$. Write a program to count the number of multiples in $a_0,a_1,a_2,\cdots,a_{j-1}$ where $0 \leq j \lt i$ for each $a[i]$ where $0 \leq i \lt n$.
For Example:
1. Input:
arr[] = {2 6 3}
Output:
no_of_multiples[] = {0,0,1} // For 2 , 6 there are no multiples present but for 3 there is one multiple present i.e. 6
2. Input:
arr[] = {16,25,63,12,65,45,23,65,78,99,36,12,36,41,36,2,3}
Output:
no_of_multiples[] ={0,0,0,0,0,0,1,0,0,0,2,1,0,2,6,9}
To solve the above problem, the algorithm which I designed is basically based on the previous problem solution but rather than updating the freq_data[]
at once I will first check how many multiples of the arr[i]
is present in the freq_data[]
and after finding all the multiples, I will increment the value at ++freq_data[data[i] - 1]
and then I will print the freq_data[i]
array after processing the whole arraarr[i]
.
Time Complexity: $O(n \times log(max))$
Space Complexity: $O(max)$
My question is: Is there any better algorithm to solve the second part i.e Write a program to count the number of multiples in $a_0,a_1,a_2,\cdots,a_{j-1}$ where $0 \leq j \lt i$ for each $a[i]$ where $0 \leq i \lt n$.
Edit-1: With reference to @gnasher729 points, there are constraints on the inputs because if the size of the input gets larger the algorithm will not give the right answer:
- $1\leq n \leq 10^5$
Constraint on the length of the sequence
- $1 \leq arr[i] \leq 10^6$
Constraint on the values of the sequence
[for each positive number given as a query, print]
the count of integral multiplesin the given array
. What isleft-sub array
- part with smaller index? Larger index? Are the values guaranteed to be increasing in value? How do you arrive at $O(max \times log(max))$ (preprocessing time)? $\endgroup$arr[i]
while traversing the array from left-right. For Example:arr[i] = {2,6,3}
then fora[0]
there are zero multiples as there is no left-subarray w.r.ta[0]
, fora[1]
there are zero multiples as there are zero multiples fora[1]
froma[0] to a[0]
, fora[2]
there is one multiple in the left-subarray{a[0],a[1]}
i.ea[1] = 6
. So the answer is[0,0,1]
$\endgroup$