Count of Array elements in given range with remainder X when divided by K for Q queries
Given an array arr[] of size N, an integer K and Q queries, each of form {x, l, r}. For each query, the task is to find the count of all elements in index range [l, r] which have remainder x when divided by K.
Examples:
Input: arr[] = {15, 28, 72, 43, 20, 0, 97}, K = 5, queries[] = {{3, 0, 3}, {0, 0, 6}, {6, 2, 4}}
Output: 2, 3, 0
Explanation: For the first query, there are 2 elements in the range [0, 3] whose remainder is 3 (28, 43).
Similarly 3 elements in range [0, 6] whose remainder is 0 (15, 20, 0).
In the third query, elements whose remainder are 6 should be found.
But for the given K = 5 possible remainders are only [0, 4]. So for any x >= K, answer will be 0.Input: arr[] = {2, 4, 6, 7, 5}, K = 3, queries[] = {{2, 1, 4}}
Output: 1
Method 1: A simple approach is, for each query, iterate through l to r and count all elements whose remainder is x.
Algorithm:
- For each query in the vector, extract the values of x, l and r from the query.
- Call the function ‘countRemainder‘ with the given parameters.
- Print the count returned by the function.
- In the function ‘countRemainder‘, initialize count as 0.
- For each index i in range l to r:
- Check if the remainder of arr[i] when divided by K is equal to x.
- If true, increment count.
- Return the count.
Below is the implementation of the approach:
C++
// C++ code for the approach #include <iostream> #include <vector> using namespace std; // Function to count elements in range [l, r] with remainder // x when divided by K int countRemainder( int arr[], int n, int K, int x, int l, int r) { int count = 0; for ( int i = l; i <= r; i++) { // Check if remainder is x // when divided by K if (arr[i] % K == x) { // Increment count if condition is true count++; } } // Return the count return count; } // Driver's code int main() { // Input array, K and Queries int arr[] = { 15, 28, 72, 43, 20, 0, 97 }; int K = 5; int N = sizeof (arr) / sizeof (arr[0]); vector<vector< int > > queries{ { 3, 0, 3 }, { 0, 0, 6 }, { 6, 2, 4 } }; for ( int i = 0; i < queries.size(); i++) { int x = queries[i][0]; int l = queries[i][1]; int r = queries[i][2]; // Function call int count = countRemainder(arr, N, K, x, l, r); cout << count << " " ; } return 0; } |
Java
// Java code for the approach import java.util.*; public class Main { // Function to count elements in range [l, r] with remainder // x when divided by K static int countRemainder( int [] arr, int n, int K, int x, int l, int r) { int count = 0 ; for ( int i = l; i <= r; i++) { // Check if remainder is x when divided by K if (arr[i] % K == x) { // Increment count if condition is true count++; } } // Return the count return count; } // Driver's code public static void main(String[] args) { // Input array, K and Queries int [] arr = { 15 , 28 , 72 , 43 , 20 , 0 , 97 }; int K = 5 ; int N = arr.length; List<List<Integer>> queries = new ArrayList<>(); queries.add(Arrays.asList( 3 , 0 , 3 )); queries.add(Arrays.asList( 0 , 0 , 6 )); queries.add(Arrays.asList( 6 , 2 , 4 )); for (List<Integer> query : queries) { int x = query.get( 0 ); int l = query.get( 1 ); int r = query.get( 2 ); // Function call int count = countRemainder(arr, N, K, x, l, r); System.out.print(count + " " ); } } } // This code is contributed by Vaibhav |
2 3 0
Time Complexity: O(N * Q)
Auxiliary Space: O(1)
Method 2: This problem can also be solved with help of precalculation based on the following idea:
Precalculate what will be the remainder, when arr[i] is divided by K and store them in a matrix (say mat[]) where mat[i][j] represents the remainder of arr[j] is i when divided by K.
Now prefix sum of ith row of the matrix gives the count of elements which will have remainder i when divided by K. Therefore, after prefix sum mat[i][j] will represent total count of elements till jth index having remainder i when divided by K.
So for a query {x, l, r} the answer will be (mat[x][r] – mat[x][l] [+1 if arr[l]%K is x])
Follow the illustration below for a better understanding of the construction of the matrix.
Illustration:
Consider arr[] = {15, 28, 72, 43, 20, 0, 97}, K = 5
Make a 2D matrix named precompute, of size (K*N), and initialize it with 0.
For the ith element, mark precompute[arr[i]%K][i] = 1, do this for all i which states that the ith element has remainder arr[i]%K.For the given example our precompute matrix will look like the following where row: remainder, column: index num.
0 1 2 3 4 5 6 0 1 0 0 0 1 1 0 1 0 0 0 0 0 0 0 2 0 0 1 0 0 0 1 3 0 1 0 1 0 0 0 4 0 0 0 0 0 0 0 Then for each row calculate prefix sum. Now matrix will look like this:
0 1 2 3 4 5 6 0 1 1 1 1 2 3 3 1 0 0 0 0 0 0 0 2 0 0 1 1 1 1 2 3 0 1 1 2 2 2 2 4 0 0 0 0 0 0 0 Here precompute[0][6] denotes that till 6th index there are a total of 3 elements which will have remainder 3 when divided by 5.
Follow the steps mentioned below to implement the idea:
- Create the 2D array (say precompute).
- Construct the array as mentioned above.
- Traverse the queries:
- For each query calculate the number of elements as per the formula shown above and store that in the answer array.
- Return the array having the answers.
Note: This method is more efficient only when the number of queries is greater than K.
Below is the implementation of the above approach:
C++
// C++ program for the above approach #include <bits/stdc++.h> using namespace std; const int MXN = 2e5; int precompute[100][MXN]; // To precompute count prefix sum of all // possible remainders void precomputation( int arr[], int n, int k) { // Mark cell whose remainder is arr[i]%k for ( int i = 0; i < n; i++) precompute[arr[i] % k][i] = 1; // Take prefix sum for all rows for ( int i = 0; i < k; i++) { for ( int j = 1; j < n; j++) { precompute[i][j] += precompute[i][j - 1]; } } } // Function to find the // count of numbers for the queries vector< int > findCount( int arr[], int K, int N, vector<vector< int > >& queries) { vector< int > res; // Initialise matrix with 0 memset (precompute, 0, sizeof precompute); // To calculate count of remainders precomputation(arr, N, K); for ( int i = 0; i < queries.size(); i++) { int x = queries[i][0]; int l = queries[i][1]; int r = queries[i][2]; if (x >= K) { res.push_back(0); continue ; } int count = precompute[x][r] - precompute[x][l] + (arr[l] % K == x); res.push_back(count); } return res; } // Driver code int main() { int arr[] = { 15, 28, 72, 43, 20, 0, 97 }; int K = 5; int N = sizeof (arr) / sizeof (arr[0]); vector<vector< int > > queries{ { 3, 0, 3 }, { 0, 0, 6 }, { 6, 2, 4 } }; vector< int > ans = findCount(arr, K, N, queries); for ( int x : ans) cout << x << " " ; return 0; } |
Java
// Java program for the above approach import java.io.*; import java.util.ArrayList; class GFG { static int MXN = 200000 ; static int [][] precompute = new int [ 100 ][MXN]; // To precompute count prefix sum of all // possible remainders static void precomputation( int [] arr, int n, int k) { // Mark cell whose remainder is arr[i]%k for ( int i = 0 ; i < n; i++) precompute[arr[i] % k][i] = 1 ; // Take prefix sum for all rows for ( int i = 0 ; i < k; i++) { for ( int j = 1 ; j < n; j++) { precompute[i][j] += precompute[i][j - 1 ]; } } } // Function to find the // count of numbers for the queries static ArrayList<Integer> findCount( int [] arr, int K, int N, int [][] queries) { ArrayList<Integer> res = new ArrayList<Integer>(); // Initialise matrix with 0 for ( int i = 0 ; i < 100 ; i++) { for ( int j = 0 ; j < MXN; j++) precompute[i][j] = 0 ; } // To calculate count of remainders precomputation(arr, N, K); for ( int i = 0 ; i < queries.length; i++) { int x = queries[i][ 0 ]; int l = queries[i][ 1 ]; int r = queries[i][ 2 ]; if (x >= K) { res.add( 0 ); continue ; } int count = precompute[x][r] - precompute[x][l] + ((arr[l] % K == x) ? 1 : 0 ); res.add(count); } return res; } // Driver code public static void main(String[] args) { int arr[] = { 15 , 28 , 72 , 43 , 20 , 0 , 97 }; int K = 5 ; int N = arr.length; int [][] queries = { { 3 , 0 , 3 }, { 0 , 0 , 6 }, { 6 , 2 , 4 } }; ArrayList<Integer> ans = findCount(arr, K, N, queries); for ( int i = 0 ; i < ans.size(); i++) System.out.print(ans.get(i) + " " ); } } // This code is contributed by phasing17 |
Python3
# python3 program for the above approach MXN = int ( 2e5 ) precompute = [[ 0 for _ in range (MXN)] for _ in range ( 100 )] # To precompute count prefix sum of all # possible remainders def precomputation(arr, n, k): global precompute # Mark cell whose remainder is arr[i]%k for i in range ( 0 , n): precompute[arr[i] % k][i] = 1 # Take prefix sum for all rows for i in range ( 0 , k): for j in range ( 1 , n): precompute[i][j] + = precompute[i][j - 1 ] # Function to find the # count of numbers for the queries def findCount(arr, K, N, queries): global precompute res = [] # Initialise matrix with 0 # To calculate count of remainders precomputation(arr, N, K) for i in range ( 0 , len (queries)): x = queries[i][ 0 ] l = queries[i][ 1 ] r = queries[i][ 2 ] if (x > = K): res.append( 0 ) continue count = precompute[x][r] - precompute[x][l] + (arr[l] % K = = x) res.append(count) return res # Driver code if __name__ = = "__main__" : arr = [ 15 , 28 , 72 , 43 , 20 , 0 , 97 ] K = 5 N = len (arr) queries = [[ 3 , 0 , 3 ], [ 0 , 0 , 6 ], [ 6 , 2 , 4 ]] ans = findCount(arr, K, N, queries) for x in ans: print (x, end = " " ) # This code is contributed by rakeshsahni |
C#
// C# code for the above discussed approach using System; using System.Collections; public class GFG { static int MXN = 200000; static int [, ] precompute = new int [100, MXN]; // To precompute count prefix sum of all // possible remainders static void precomputation( int [] arr, int n, int k) { // Mark cell whose remainder is arr[i]%k for ( int i = 0; i < n; i++) precompute[arr[i] % k, i] = 1; // Take prefix sum for all rows for ( int i = 0; i < k; i++) { for ( int j = 1; j < n; j++) { precompute[i, j] += precompute[i, j - 1]; } } } // Function to find the // count of numbers for the queries static ArrayList findCount( int [] arr, int K, int N, int [, ] queries) { var res = new ArrayList(); // Initialise matrix with 0 for ( int i = 0; i < 100; i++) { for ( int j = 0; j < MXN; j++) precompute[i, j] = 0; } // To calculate count of remainders precomputation(arr, N, K); for ( int i = 0; i < queries.GetLength(0); i++) { int x = queries[i, 0]; int l = queries[i, 1]; int r = queries[i, 2]; if (x >= K) { res.Add(0); continue ; } int count = precompute[x, r] - precompute[x, l] + ((arr[l] % K == x) ? 1 : 0); res.Add(count); } return res; } // Driver Code public static void Main( string [] args) { int [] arr = { 15, 28, 72, 43, 20, 0, 97 }; int K = 5; int N = arr.Length; int [, ] queries = { { 3, 0, 3 }, { 0, 0, 6 }, { 6, 2, 4 } }; ArrayList ans = findCount(arr, K, N, queries); for ( int i = 0; i < ans.Count; i++) Console.Write(ans[i] + " " ); } } // This code is contributed by phasing17 |
Javascript
<script> // JavaScript code for the above approach let MXN = 2e5; let precompute = new Array(100); for (let i = 0; i < precompute.length; i++) { precompute[i] = new Array(MXN).fill(0); } // To precompute count prefix sum of all // possible remainders function precomputation(arr, n, k) { // Mark cell whose remainder is arr[i]%k for (let i = 0; i < n; i++) precompute[arr[i] % k][i] = 1; // Take prefix sum for all rows for (let i = 0; i < k; i++) { for (let j = 1; j < n; j++) { precompute[i][j] += precompute[i][j - 1]; } } } // Function to find the // count of numbers for the queries function findCount(arr, K, N, queries) { let res = []; // To calculate count of remainders precomputation(arr, N, K); for (let i = 0; i < queries.length; i++) { let x = queries[i][0]; let l = queries[i][1]; let r = queries[i][2]; if (x >= K) { res.push(0); continue ; } let count = precompute[x][r] - precompute[x][l] + (arr[l] % K == x); res.push(count); } return res; } // Driver code let arr = [15, 28, 72, 43, 20, 0, 97]; let K = 5; let N = arr.length; let queries = [[3, 0, 3], [0, 0, 6], [6, 2, 4]]; let ans = findCount(arr, K, N, queries); for (let x of ans) document.write(x + " " ) // This code is contributed by Potta Lokesh </script> |
2 3 0
Time Complexity: O(Q + K*N)
Auxiliary Space: O(K*N)
Please Login to comment...