Given an array arr[] and an integer K, the task is to count the number of sub-arrays having bitwise OR ? K.
Examples:
Input: arr[] = { 1, 2, 3 } K = 3
Output: 4
Bitwise OR of sub-arrays:
{ 1 } = 1
{ 1, 2 } = 3
{ 1, 2, 3 } = 3
{ 2 } = 2
{ 2, 3 } = 3
{ 3 } = 3
4 sub-arrays have bitwise OR ? KInput: arr[] = { 3, 4, 5 } K = 6
Output: 2
Naive approach: Run three nested loops. The outermost loop determines the starting of the sub-array. The middle loop determines the ending of the sub-array. The innermost loop traverses the sub-array whose bounds are determined by the outermost and middle loops. For every sub-array, calculate OR and update count = count + 1 if OR is greater than K.
Below is the implementation of the above approach:
C++
// C++ implementation of the approach #include <bits/stdc++.h> using namespace std; // Function to return the count of required sub-arrays int countSubArrays( const int * arr, int n, int K) { int count = 0; for ( int i = 0; i < n; i++) { for ( int j = i; j < n; j++) { int bitwise_or = 0; // Traverse sub-array [i..j] for ( int k = i; k <= j; k++) { bitwise_or = bitwise_or | arr[k]; } if (bitwise_or >= K) count++; } } return count; } // Driver code int main() { int arr[] = { 3, 4, 5 }; int n = sizeof (arr) / sizeof (arr[0]); int k = 6; cout << countSubArrays(arr, n, k); return 0; } |
Java
// Java implementation of the approach import java.util.*; class solution { // Function to return the count of required sub-arrays static int countSubArrays( int arr[], int n, int K) { int count = 0 ; for ( int i = 0 ; i < n; i++) { for ( int j = i; j < n; j++) { int bitwise_or = 0 ; // Traverse sub-array [i..j] for ( int k = i; k <= j; k++) { bitwise_or = bitwise_or | arr[k]; } if (bitwise_or >= K) count++; } } return count; } // Driver code public static void main(String args[]) { int arr[] = { 3 , 4 , 5 }; int n = arr.length; int k = 6 ; System.out.println(countSubArrays(arr, n, k)); } } // This code is contributed by // Surendra_Gangwar |
Python3
# Python3 implementation of the approach # Function to return the count of # required sub-arrays def countSubArrays(arr, n, K) : count = 0 ; for i in range (n) : for j in range (i, n) : bitwise_or = 0 # Traverse sub-array [i..j] for k in range (i, j + 1 ) : bitwise_or = bitwise_or | arr[k] if (bitwise_or > = K) : count + = 1 return count # Driver code if __name__ = = "__main__" : arr = [ 3 , 4 , 5 ] n = len (arr) k = 6 print (countSubArrays(arr, n, k)) # This code is contributed by Ryuga |
C#
// C# implementation of the approach using System; class GFG { // Function to return the count of // required sub-arrays static int countSubArrays( int []arr, int n, int K) { int count = 0; for ( int i = 0; i < n; i++) { for ( int j = i; j < n; j++) { int bitwise_or = 0; // Traverse sub-array [i..j] for ( int k = i; k <= j; k++) { bitwise_or = bitwise_or | arr[k]; } if (bitwise_or >= K) count++; } } return count; } // Driver code public static void Main() { int []arr = { 3, 4, 5 }; int n = arr.Length; int k = 6; Console.WriteLine(countSubArrays(arr, n, k)); } } // This code is contributed by // Mohit kumar |
PHP
<?php // PHP implementation of the approach // Function to return the count of // required sub-arrays function countSubArrays( $arr , $n , $K ) { $count = 0; for ( $i = 0; $i < $n ; $i ++) { for ( $j = 0; $j < $n ; $j ++) { $bitwise_or = 0; // Traverse sub-array [i..j] for ( $k = $i ; $k < $j + 1; $k ++) $bitwise_or = $bitwise_or | $arr [ $k ]; if ( $bitwise_or >= $K ) $count += 1; } } return $count ; } // Driver code $arr = array ( 3, 4, 5 ); $n = count ( $arr ); $k = 6; print (countSubArrays( $arr , $n , $k )); // This code is contributed by mits ?> |
Javascript
<script> // Javascript implementation of the approach // Function to return the count of required sub-arrays function countSubArrays(arr, n, K) { let count = 0; for (let i = 0; i < n; i++) { for (let j = i; j < n; j++) { let bitwise_or = 0; // Traverse sub-array [i..j] for (let k = i; k <= j; k++) { bitwise_or = bitwise_or | arr[k]; } if (bitwise_or >= K) count++; } } return count; } // Driver code let arr = [ 3, 4, 5 ]; let n = arr.length; let k = 6; document.write(countSubArrays(arr, n, k)); // This code is contributed by suresh07. </script> |
2
The time complexity of the above solution is O(n3) and Auxiliary Space is O(1).
An efficient solution uses segment trees to calculate bitwise OR of a sub-array in O(log n) time. Hence, now we directly query the segment tree instead of traversing the sub-array.
Below is the implementation of the above approach:
C++
// C++ implementation of the approach #include <bits/stdc++.h> using namespace std; #define N 100002 int tree[4 * N]; // Function to build the segment tree void build( int * arr, int node, int start, int end) { if (start == end) { tree[node] = arr[start]; return ; } int mid = (start + end) >> 1; build(arr, 2 * node, start, mid); build(arr, 2 * node + 1, mid + 1, end); tree[node] = tree[2 * node] | tree[2 * node + 1]; } // Function to return the bitwise OR of segment [L..R] int query( int node, int start, int end, int l, int r) { if (start > end || start > r || end < l) { return 0; } if (start >= l && end <= r) { return tree[node]; } int mid = (start + end) >> 1; int q1 = query(2 * node, start, mid, l, r); int q2 = query(2 * node + 1, mid + 1, end, l, r); return q1 | q2; } // Function to return the count of required sub-arrays int countSubArrays( int arr[], int n, int K) { // Build segment tree build(arr, 1, 0, n - 1); int count = 0; for ( int i = 0; i < n; i++) { for ( int j = i; j < n; j++) { // Query segment tree for bitwise OR // of sub-array [i..j] int bitwise_or = query(1, 0, n - 1, i, j); if (bitwise_or >= K) count++; } } return count; } // Driver code int main() { int arr[] = { 3, 4, 5 }; int n = sizeof (arr) / sizeof (arr[0]); int k = 6; cout << countSubArrays(arr, n, k); return 0; } |
Java
// Java implementation of the approach public class Main { static int N = 100002 ; static int tree[] = new int [ 4 * N]; // Function to build the segment tree static void build( int arr[], int node, int start, int end) { if (start == end) { tree[node] = arr[start]; return ; } int mid = (start + end) >> 1 ; build(arr, 2 * node, start, mid); build(arr, 2 * node + 1 , mid + 1 , end); tree[node] = tree[ 2 * node] | tree[ 2 * node + 1 ]; } // Function to return the bitwise OR of segment [L..R] static int query( int node, int start, int end, int l, int r) { if (start > end || start > r || end < l) { return 0 ; } if (start >= l && end <= r) { return tree[node]; } int mid = (start + end) >> 1 ; int q1 = query( 2 * node, start, mid, l, r); int q2 = query( 2 * node + 1 , mid + 1 , end, l, r); return q1 | q2; } // Function to return the count of required sub-arrays static int countSubArrays( int arr[], int n, int K) { // Build segment tree build(arr, 1 , 0 , n - 1 ); int count = 0 ; for ( int i = 0 ; i < n; i++) { for ( int j = i; j < n; j++) { // Query segment tree for bitwise OR // of sub-array [i..j] int bitwise_or = query( 1 , 0 , n - 1 , i, j); if (bitwise_or >= K) count++; } } return count; } // Driver code public static void main(String[] args) { int arr[] = { 3 , 4 , 5 }; int n = arr.length; int k = 6 ; System.out.print(countSubArrays(arr, n, k)); } } // This code is contributed by divyesh072019 |
Python3
# Python implementation of the approach N = 100002 tree = [ 0 ] * ( 4 * N) # Function to build the segment tree def build(arr, node, start, end): if start = = end: tree[node] = arr[start] return mid = (start + end) >> 1 build(arr, 2 * node, start, mid) build(arr, 2 * node + 1 , mid + 1 , end) tree[node] = tree[ 2 * node] | tree[ 2 * node + 1 ] # Function to return the bitwise OR of segment[L..R] def query(node, start, end, l, r): if start > end or start > r or end < l: return 0 if start > = l and end < = r: return tree[node] mid = (start + end) >> 1 q1 = query( 2 * node, start, mid, l, r) q2 = query( 2 * node + 1 , mid + 1 , end, l, r) return q1 or q2 # Function to return the count of required sub-arrays def countSubArrays(arr, n, K): # Build segment tree build(arr, 1 , 0 , n - 1 ) count = 0 for i in range (n): for j in range (n): # Query segment tree for bitwise OR # of sub-array[i..j] bitwise_or = query( 1 , 0 , n - 1 , i, j) if bitwise_or > = K: count + = 1 return count # Driver code arr = [ 3 , 4 , 5 ] n = len (arr) k = 6 print (countSubArrays(arr, n, k)) # This code is contributed by ankush_953 |
C#
// C# implementation of the approach using System; class GFG { static int N = 100002; static int [] tree = new int [4 * N]; // Function to build the segment tree static void build( int [] arr, int node, int start, int end) { if (start == end) { tree[node] = arr[start]; return ; } int mid = (start + end) >> 1; build(arr, 2 * node, start, mid); build(arr, 2 * node + 1, mid + 1, end); tree[node] = tree[2 * node] | tree[2 * node + 1]; } // Function to return the bitwise OR of segment [L..R] static int query( int node, int start, int end, int l, int r) { if (start > end || start > r || end < l) { return 0; } if (start >= l && end <= r) { return tree[node]; } int mid = (start + end) >> 1; int q1 = query(2 * node, start, mid, l, r); int q2 = query(2 * node + 1, mid + 1, end, l, r); return q1 | q2; } // Function to return the count of required sub-arrays static int countSubArrays( int [] arr, int n, int K) { // Build segment tree build(arr, 1, 0, n - 1); int count = 0; for ( int i = 0; i < n; i++) { for ( int j = i; j < n; j++) { // Query segment tree for bitwise OR // of sub-array [i..j] int bitwise_or = query(1, 0, n - 1, i, j); if (bitwise_or >= K) count++; } } return count; } // Driver code static void Main() { int [] arr = { 3, 4, 5 }; int n = arr.Length; int k = 6; Console.WriteLine(countSubArrays(arr, n, k)); } } // This code is contributed by divyeshrabadiya07. |
Javascript
<script> // Javascript implementation of the approach let N = 100002; let tree = new Array(4 * N); // Function to build the segment tree function build(arr, node, start, end) { if (start == end) { tree[node] = arr[start]; return ; } let mid = (start + end) >> 1; build(arr, 2 * node, start, mid); build(arr, 2 * node + 1, mid + 1, end); tree[node] = tree[2 * node] | tree[2 * node + 1]; } // Function to return the bitwise OR of segment [L..R] function query(node, start, end, l, r) { if (start > end || start > r || end < l) { return 0; } if (start >= l && end <= r) { return tree[node]; } let mid = (start + end) >> 1; let q1 = query(2 * node, start, mid, l, r); let q2 = query(2 * node + 1, mid + 1, end, l, r); return q1 | q2; } // Function to return the count of // required sub-arrays function countSubArrays(arr, n, K) { // Build segment tree build(arr, 1, 0, n - 1); let count = 0; for (let i = 0; i < n; i++) { for (let j = i; j < n; j++) { // Query segment tree for bitwise OR // of sub-array [i..j] let bitwise_or = query(1, 0, n - 1, i, j); if (bitwise_or >= K) count++; } } return count; } // Driver code let arr = [ 3, 4, 5 ]; let n = arr.length; let k = 6; document.write(countSubArrays(arr, n, k)); // This code is contributed by rag2127 </script> |
2
Complexity Analysis:
- Time complexity: O(n2 log n).
- Auxiliary Space: O(n).
A further efficient solution uses binary search. Bitwise OR is a function that never decreases with the number of inputs. For example:
OR(a, b) ? OR(a, b, c)
OR(a1, a2, a3, …) ? OR(a1, a2, a3, …, b)
By this property, OR(ai, …, aj) <= OR(ai, …, aj, aj+1). Hence, if OR(ai, …, aj) is greater than K then OR(ai, …, aj, aj+1) will also be greater than K. Hence, once we find a subarray [i..j] whose OR is greater than K, we don’t need to check subarrays [i..j+1], [i..j+2], .. and so on, because their OR will also be greater than K. We can add the count of remaining subarrays to the current sum. The first subarray from a particular starting point whose OR is greater than K is found using binary search.
Below is the implementation of the above idea:
C++
// C++ program to implement the above approach #include <bits/stdc++.h> #define N 100002 using namespace std; int tree[4 * N]; // Function which builds the segment tree void build( int * arr, int node, int start, int end) { if (start == end) { tree[node] = arr[start]; return ; } int mid = (start + end) >> 1; build(arr, 2 * node, start, mid); build(arr, 2 * node + 1, mid + 1, end); tree[node] = tree[2 * node] | tree[2 * node + 1]; } // Function that returns bitwise OR of segment [L..R] int query( int node, int start, int end, int l, int r) { if (start > end || start > r || end < l) { return 0; } if (start >= l && end <= r) { return tree[node]; } int mid = (start + end) >> 1; int q1 = query(2 * node, start, mid, l, r); int q2 = query(2 * node + 1, mid + 1, end, l, r); return q1 | q2; } // Function to count requisite number of subarrays int countSubArrays( const int * arr, int n, int K) { int count = 0; for ( int i = 0; i < n; i++) { // Check for subarrays starting with index i int low = i, high = n - 1, index = INT_MAX; while (low <= high) { int mid = (low + high) >> 1; // If OR of subarray [i..mid] >= K, // then all subsequent subarrays will have OR >= K // therefore reduce high to mid - 1 // to find the minimal length subarray // [i..mid] having OR >= K if (query(1, 0, n - 1, i, mid) >= K) { index = min(index, mid); high = mid - 1; } else { low = mid + 1; } } // Increase count with number of subarrays // having OR >= K and starting with index i if (index != INT_MAX) { count += n - index; } } return count; } // Driver code int main() { int arr[] = { 3, 4, 5 }; int n = sizeof (arr) / sizeof (arr[0]); // Build segment tree. build(arr, 1, 0, n - 1); int k = 6; cout << countSubArrays(arr, n, k); return 0; } |
Java
// Java implementation of the above approach class GFG { static int N = 100002 ; static int tree[] = new int [ 4 * N]; // Function which builds the segment tree static void build( int [] arr, int node, int start, int end) { if (start == end) { tree[node] = arr[start]; return ; } int mid = (start + end) >> 1 ; build(arr, 2 * node, start, mid); build(arr, 2 * node + 1 , mid + 1 , end); tree[node] = tree[ 2 * node] | tree[ 2 * node + 1 ]; } // Function that returns bitwise // OR of segment [L..R] static int query( int node, int start, int end, int l, int r) { if (start > end || start > r || end < l) { return 0 ; } if (start >= l && end <= r) { return tree[node]; } int mid = (start + end) >> 1 ; int q1 = query( 2 * node, start, mid, l, r); int q2 = query( 2 * node + 1 , mid + 1 , end, l, r); return q1 | q2; } // Function to count requisite number of subarrays static int countSubArrays( int [] arr, int n, int K) { int count = 0 ; for ( int i = 0 ; i < n; i++) { // Check for subarrays starting with index i int low = i, high = n - 1 , index = Integer.MAX_VALUE; while (low <= high) { int mid = (low + high) >> 1 ; // If OR of subarray [i..mid] >= K, // then all subsequent subarrays will // have OR >= K therefore reduce // high to mid - 1 to find the // minimal length subarray // [i..mid] having OR >= K if (query( 1 , 0 , n - 1 , i, mid) >= K) { index = Math.min(index, mid); high = mid - 1 ; } else { low = mid + 1 ; } } // Increase count with number of subarrays // having OR >= K and starting with index i if (index != Integer.MAX_VALUE) { count += n - index; } } return count; } // Driver code public static void main(String[] args) { int arr[] = { 3 , 4 , 5 }; int n = arr.length; // Build segment tree. build(arr, 1 , 0 , n - 1 ); int k = 6 ; System.out.println(countSubArrays(arr, n, k)); } } // This code is contributed by Rajput-Ji |
Python3
# Python3 program to implement the above approach N = 100002 tree = [ 0 for i in range ( 4 * N)]; # Function which builds the segment tree def build(arr, node, start, end): if (start = = end): tree[node] = arr[start]; return ; mid = (start + end) >> 1 ; build(arr, 2 * node, start, mid); build(arr, 2 * node + 1 , mid + 1 , end); tree[node] = tree[ 2 * node] | tree[ 2 * node + 1 ]; # Function that returns bitwise OR of segment [L..R] def query(node, start, end, l, r): if (start > end or start > r or end < l): return 0 ; if (start > = l and end < = r): return tree[node]; mid = (start + end) >> 1 ; q1 = query( 2 * node, start, mid, l, r); q2 = query( 2 * node + 1 , mid + 1 , end, l, r); return q1 | q2; # Function to count requisite number of subarrays def countSubArrays(arr, n, K): count = 0 ; for i in range (n): # Check for subarrays starting with index i low = i high = n - 1 index = 1000000000 while (low < = high): mid = (low + high) >> 1 ; # If OR of subarray [i..mid] >= K, # then all subsequent subarrays will have OR >= K # therefore reduce high to mid - 1 # to find the minimal length subarray # [i..mid] having OR >= K if (query( 1 , 0 , n - 1 , i, mid) > = K): index = min (index, mid); high = mid - 1 ; else : low = mid + 1 ; # Increase count with number of subarrays # having OR >= K and starting with index i if (index ! = 1000000000 ): count + = n - index; return count; # Driver code if __name__ = = '__main__' : arr = [ 3 , 4 , 5 ] n = len (arr) # Build segment tree. build(arr, 1 , 0 , n - 1 ); k = 6 ; print (countSubArrays(arr, n, k)) # This code is contributed by rutvik_56. |
C#
// C# implementation of the above approach using System; class GFG { static int N = 100002; static int []tree = new int [4 * N]; // Function which builds the segment tree static void build( int [] arr, int node, int start, int end) { if (start == end) { tree[node] = arr[start]; return ; } int mid = (start + end) >> 1; build(arr, 2 * node, start, mid); build(arr, 2 * node + 1, mid + 1, end); tree[node] = tree[2 * node] | tree[2 * node + 1]; } // Function that returns bitwise // OR of segment [L..R] static int query( int node, int start, int end, int l, int r) { if (start > end || start > r || end < l) { return 0; } if (start >= l && end <= r) { return tree[node]; } int mid = (start + end) >> 1; int q1 = query(2 * node, start, mid, l, r); int q2 = query(2 * node + 1, mid + 1, end, l, r); return q1 | q2; } // Function to count requisite number of subarrays static int countSubArrays( int [] arr, int n, int K) { int count = 0; for ( int i = 0; i < n; i++) { // Check for subarrays starting with index i int low = i, high = n - 1, index = int .MaxValue; while (low <= high) { int mid = (low + high) >> 1; // If OR of subarray [i..mid] >= K, // then all subsequent subarrays will // have OR >= K therefore reduce // high to mid - 1 to find the // minimal length subarray // [i..mid] having OR >= K if (query(1, 0, n - 1, i, mid) >= K) { index = Math.Min(index, mid); high = mid - 1; } else { low = mid + 1; } } // Increase count with number of subarrays // having OR >= K and starting with index i if (index != int .MaxValue) { count += n - index; } } return count; } // Driver code public static void Main(String[] args) { int []arr = {3, 4, 5}; int n = arr.Length; // Build segment tree. build(arr, 1, 0, n - 1); int k = 6; Console.WriteLine(countSubArrays(arr, n, k)); } } // This code is contributed by PrinciRaj1992 |
Javascript
<script> // JavaScript implementation of the above approach let N = 100002; let tree= new Array(4*N); // Function which builds the segment tree function build(arr,node,start,end) { if (start == end) { tree[node] = arr[start]; return ; } let mid = (start + end) >> 1; build(arr, 2 * node, start, mid); build(arr, 2 * node + 1, mid + 1, end); tree[node] = tree[2 * node] | tree[2 * node + 1]; } // Function that returns bitwise // OR of segment [L..R] function query(node,start,end,l,r) { if (start > end || start > r || end < l) { return 0; } if (start >= l && end <= r) { return tree[node]; } let mid = (start + end) >> 1; let q1 = query(2 * node, start, mid, l, r); let q2 = query(2 * node + 1, mid + 1, end, l, r); return q1 | q2; } // Function to count requisite number of subarrays function countSubArrays(arr,n,K) { let count = 0; for (let i = 0; i < n; i++) { // Check for subarrays starting with index i let low = i, high = n - 1, index = Number.MAX_VALUE; while (low <= high) { let mid = (low + high) >> 1; // If OR of subarray [i..mid] >= K, // then all subsequent subarrays will // have OR >= K therefore reduce // high to mid - 1 to find the // minimal length subarray // [i..mid] having OR >= K if (query(1, 0, n - 1, i, mid) >= K) { index = Math.min(index, mid); high = mid - 1; } else { low = mid + 1; } } // Increase count with number of subarrays // having OR >= K and starting with index i if (index != Number.MAX_VALUE) { count += n - index; } } return count; } // Driver code let arr=[3, 4, 5]; let n = arr.length; // Build segment tree. build(arr, 1, 0, n - 1); let k = 6; document.write(countSubArrays(arr, n, k)); // This code is contributed by patel2127 </script> |
2
Complexity Analysis:
- Time complexity: O(n log2 n).
- Auxiliary Space: O(n).
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 neveropen!