
Data Structure
Networking
RDBMS
Operating System
Java
MS Excel
iOS
HTML
CSS
Android
Python
C Programming
C++
C#
MongoDB
MySQL
Javascript
PHP
- Selected Reading
- UPSC IAS Exams Notes
- Developer's Best Practices
- Questions and Answers
- Effective Resume Writing
- HR Interview Questions
- Computer Glossary
- Who is Who
Check If Any Valid Sequence is Divisible by M
A sequence is a collection of objects, and in our case, it is a collection of integers. The task is to find if a sequence with the usage of the addition and subtraction operator within the elements is divisible by M or not.
Problem Statement
Given an integer M and an array of integers. Using only addition and subtraction between elements check if there is a valid sequence whose solution is divisible by M.
Sample Example 1
Input: M = 2, arr = {1, 2, 5}
Output: TRUE
Explanation ? For the given array a valid sequence {1 + 2 + 5} = {8} is possible which is divisible by 2.
Sample Example 2
Input: M = 4, arr = {1, 2}
Output: FALSE
Explanation ? For the given array no sequence is possible whose solution is divisible by 4.
Approach 1: Brute Force Approach
A simple solution to the problem is to find all the possible sequences of the array using a recursive function and then check if any sequence is divisible by M.
Pseudocode
procedure divisible (M, arr[], index, sum, n) if index == n if sum is a multiple of M ans = TRUE end if ans = false end if divisible(M, arr, index + 1, sum + arr[index], n) or divisible(M, arr, index + 1, sum - arr[index], n) end procedure
Example: C++ Implementation
In the following program, we use a recursive approach to find all the valid sequences and then check if any valid sequence is divisible by M.
#include <bits/stdc++.h> using namespace std; // Recusive function to find if a valid sequence is divisible by M or not bool divisible(int M, int arr[], int index, int sum, int n){ // Cheking the divisiblilty by M when the array ends if (index == n) { if (sum % M == 0){ return true; } return false; } // If either of addition or subtraction is true, return true return divisible(M, arr, index + 1, sum + arr[index], n) || divisible(M, arr, index + 1, sum - arr[index], n); } int main(){ int M = 4, arr[2] = {1, 5}; if (divisible(M, arr, 0, 0, 2)){ cout << "TRUE"; } else{ cout << " FALSE"; } return 0; }
Output
TRUE
Time Complexity ? O(2^n) due to use of recursion.
Space Complexity ? O(n) due to the recursive stack space.
Approach 2: Backtracking
This approach is similar to the previous brute force recursive approach except that using backtracking we can backtrack the search space to not go on a path that we know does not have a valid sequence divisible by M.
Pseudocode
procedure divisible (M, arr[], index, sum, n) if index == n if sum is a multiple of M ans = TRUE end if ans = false end if if divisible(M, arr, index + 1, sum + arr[index], n) ans = true end if if divisible(M, arr, index + 1, sum - arr[index], n) ans = true end if ans = false end procedure
Example: C++ Implementation
In the following program, we prune the search space using backtracking to find the solution to the problem.
#include <bits/stdc++.h> using namespace std; // Function to find if a valid sequence is divisible by M or not bool divisible(int M, int arr[], int index, int sum, int n){ // Cheking the divisiblilty by M when the array ends if (index == n){ if (sum % M == 0){ return true; } return false; } // Checking the divisibility of sum + arr[index] if (divisible(M, arr, index + 1, sum + arr[index], n)){ return true; } // Checking the divisibility of sum - arr[index] if (divisible(M, arr, index + 1, sum - arr[index], n)){ return true; } return false; } int main(){ int M = 4, arr[2] = {1, 5}; if (divisible(M, arr, 0, 0, 2)){ cout << "TRUE"; } else{ cout << " FALSE"; } return 0; }
Output
TRUE
Time Complexity ? O(2^n) for worst case scenario but in practise it is better than brute force approach due to pruning of search space.
Space Complexity ? O(n) due to recursive stack space.
Approach 3: Greedy Approach
A greedy solution to the problem is to first sort array in increasing order and then greedily applying addition function if the sum does not exceed M. This approach may not give the global optimal solution but gives the local optimal solution.
Pseudocode
procedure divisible (M, arr[]) sum = 0 for i = 1 to end of arr sum = sum + arr[i] if sum is divisible by M ans = true end if sort array arr[] i = 0 j = last index of array while i < j if arr[j] - arr[i] is divisible by M ans = true end if if sum % M == (sum - arr[j]) % M sum = sum - arr[j] j = j - 1 else sum = sum - arr[i] i = i + 1 end if ans = false end procedure
Example: C++ Implemenation
In the following program, array is sorted to find optimal local subarray divisible by M.
#include <bits/stdc++.h> using namespace std; // Greedy function to find if a valid sequence is divisible by M or not bool divisible(int M, vector<int> &arr){ int sum = 0; for (int i = 0; i < arr.size(); i++) { sum += arr[i]; } // Checking if sumof all elements is divisible by M if (sum % M == 0){ return true; } sort(arr.begin(), arr.end()); int i = 0, j = arr.size() - 1; while (i < j){ // Checking if the difference between the largest and smallest element at a time in the array is divisible by M if ((arr[j] - arr[i]) % M == 0){ return true; } // Removing either the largest or smallest element based on which does not affect the sum's divisibility if (sum % M == (sum - arr[i]) % M){ sum -= arr[i]; i++; } else{ sum -= arr[j]; j--; } } return false; } int main(){ int M = 4; int array[2] = {1, 3}; vector<int> arr(array, array + 2); if (divisible(M, arr)){ cout << "TRUE"; } else{ cout << " FALSE"; } return 0; }
Output
TRUE
Approach 4: Dynamic Programming
Using the concept of dynamic programming, in this solution we store the intermediate results of evaluation. We'll create a table with N+1 rows and M columns and the base case where result % M == 0 when we use no element of array. Then iterating over all possible remainders of modulo M, we update the table.
Pseudocode
procedure divisible (arr[], M , N) dp[N+1][M] = false dp[0][0] = true for i = 1 to N for i = j to M mod = arr[ i- 1] % M dp[i][j] = dp[i - 1][(j - mod + M) % M] or dp[i - 1][(j + mod) % M] ans = dp[N][0] end procedure
Example: C++ Implementation
In the following program we split the problem in subprobles and then solve them.
#include <bits/stdc++.h> using namespace std; // Function to find if a valid sequence is divisible by M or not bool divisible(int arr[], int M, int N){ // Creating the dp table of size N+1 * M vector<vector<bool> > dp(N + 1, vector<bool>(M, false)); // Base case dp[0][0] = true; // For each element iterating over all possible remainders j modulo M for (int i = 1; i <= N; i++){ for (int j = 0; j < M; j++){ int mod = arr[i - 1] % M; // Either exclude or include the current element in the table dp[i][j] = dp[i - 1][(j - mod + M) % M] || dp[i - 1][(j + mod) % M]; } } return dp[N][0]; } int main(){ int M = 4; int arr[2] = {1, 3}; if (divisible(arr, M, 2)){ cout << "TRUE"; } else{ cout << " FALSE"; } return 0; }
Output
TRUE
Conclusion
In conclusion, for finding a valid sequence divisible by M, we can apply multiple approaches with varying tiem and space analysis ranging from O(2^n) in the case of brute force to O(NM) in the case of dynamic programming which is the most efficient approach.