Count distinct Bitwise OR of all Subarrays
Given an array A of non-negative integers, where . The task is to count number of distinct possible results obtained by taking the bitwise OR of all the elements in all possible Subarrays.
Examples:
Input: A = [1, 2]
Output: 3
Explanation: The possible subarrays are [1], [2], [1, 2].
These Bitwise OR of subarrays are 1, 2, 3.
There are 3 distinct values, so the answer is 3.
Input: A = [1, 2, 4]
Output: 6
Explanation: The possible distinct values are 1, 2, 3, 4, 6, and 7.
Approach: The Naive approach is to generate all possible subarrays and take bitwise OR of all elements in the subarray. Store each result in set and return length of the set.
Efficient Approach: We can make the above approach better. The Naive approach is to calculate all possible result where, res(i, j) = A[i] | A[i+1] | … | A[j]. However we can speed this up by taking note of the fact that res(i, j+1) = res(i, j) | A[j+1]. At the kth step, say we have all of the res(i, k) in some set pre. Then we can find the next pre set (for k -> k+1) by using res(i, k+1) = res(i, k) | A[k+1].
However, the number of unique values in this set pre is atmost 32, since the list res(k, k), res(k-1, k), res(k-2, k), … is monotone increasing, and any subsequent values that are different from previous must have more 1’s in it’s binary representation which can have maximum of 32 ones.
Below is the implementation of above approach.
C++
#include <iostream>
#include <vector>
#include <set>
using namespace std;
int subarrayBitwiseOR(vector< int >& A) {
set< int > res;
set< int > pre;
pre.insert(0);
for ( int x : A) {
set< int > temp;
for ( int y : pre) {
temp.insert(x | y);
}
temp.insert(x);
pre = temp;
res.insert(pre.begin(), pre.end());
}
return res.size();
}
int main() {
vector< int > A = {1, 2, 4};
cout << subarrayBitwiseOR(A) << endl;
return 0;
}
|
Java
import java.util.*;
class Main {
public static int subarrayBitwiseOR( int [] A) {
Set<Integer> res = new HashSet<>();
Set<Integer> pre = new HashSet<>();
pre.add( 0 );
for ( int x : A) {
Set<Integer> temp = new HashSet<>();
for ( int y : pre) {
temp.add(x | y);
}
temp.add(x);
pre = temp;
res.addAll(pre);
}
return res.size();
}
public static void main(String[] args) {
int [] A = { 1 , 2 , 4 };
System.out.println(subarrayBitwiseOR(A));
}
}
|
Python
def subarrayBitwiseOR(A):
res = set ()
pre = { 0 }
for x in A:
pre = {x | y for y in pre} | {x}
res | = pre
return len (res)
A = [ 1 , 2 , 4 ]
print (subarrayBitwiseOR(A))
|
C#
using System;
using System.Collections.Generic;
class MainClass {
public static int subarrayBitwiseOR( int [] A) {
HashSet< int > res = new HashSet< int >();
HashSet< int > pre = new HashSet< int >();
pre.Add(0);
foreach ( int x in A) {
HashSet< int > temp = new HashSet< int >();
foreach ( int y in pre) {
temp.Add(x | y);
}
temp.Add(x);
pre = temp;
res.UnionWith(pre);
}
return res.Count;
}
public static void Main( string [] args) {
int [] A = {1, 2, 4};
Console.WriteLine(subarrayBitwiseOR(A));
}
}
|
Javascript
function subarrayBitwiseOR(A) {
let res = new Set();
let pre = new Set([0]);
for (let x of A) {
let temp = new Set();
for (let y of pre) {
temp.add(x | y);
}
temp.add(x);
res = new Set([...res, ...temp]);
pre = new Set(temp);
}
return res.size;
}
let A = [1, 2, 4];
console.log(subarrayBitwiseOR(A));
|
Time Complexity: O(N*log(K)), where N is the length of A, and K is the maximum size of elements in A.
C++ implementation of the above approach.
C++
#include <bits/stdc++.h>
using namespace std;
int distintBitwiseOR( int arr[], int n)
{
unordered_set< int > ans, prev;
for ( int i = 0; i < n; i++) {
unordered_set< int > ne;
for ( auto x : prev)
ne.insert(arr[i] | x);
ne.insert(arr[i]);
for ( auto x : ne)
ans.insert(x);
prev = ne;
}
return ans.size();
}
int main()
{
int n = 3;
int arr[] = { 1, 2, 4 };
cout << distintBitwiseOR(arr, n);
return 0;
}
|
Java
import java.io.*;
import java.util.*;
class GFG
{
static int distintBitwiseOR( int arr[], int n)
{
HashSet<Integer>ans = new HashSet<>();
HashSet<Integer>prev = new HashSet<>();
for ( int i = 0 ; i < n; i++)
{
HashSet<Integer>ne = new HashSet<>();
ne.add(arr[i]);
for ( int x :prev)
{
ne.add(arr[i]|x);
}
for ( int x :ne)
{
ans.add(x);
}
prev = ne;
}
return ans.size();
}
public static void main (String[] args) {
int n = 3 ;
int arr[] = { 1 , 2 , 4 };
System.out.println(distintBitwiseOR(arr, n));
}
}
|
Python3
def distintBitwiseOR(arr,n):
ans,prev = set (), set ()
for i in range (n):
ne = set ()
for x in prev:
ne.add(arr[i] | x)
ne.add(arr[i])
for x in ne:
ans.add(x)
prev = ne
return len (ans)
n = 3
arr = [ 1 , 2 , 4 ]
print (distintBitwiseOR(arr, n))
|
C#
using System;
using System.Collections.Generic;
public class GFG
{
static int distintBitwiseOR( int [] arr, int n)
{
HashSet< int > ans = new HashSet< int >();
HashSet< int > prev = new HashSet< int >();
for ( int i = 0; i < n; i++) {
HashSet< int > ne = new HashSet< int >();
ne.Add(arr[i]);
foreach ( var x in prev) { ne.Add(arr[i] | x); }
foreach ( var x in ne) { ans.Add(x); }
prev = ne;
}
return ans.Count;
}
public static void Main( string [] args)
{
int n = 3;
int [] arr = { 1, 2, 4 };
Console.WriteLine(distintBitwiseOR(arr, n));
}
}
|
Javascript
<script>
function distintBitwiseOR(arr,n)
{
let ans = new Set(), prev = new Set();
for (let i = 0; i < n; i++) {
let ne = new Set();
for (let x of prev)
ne.add(arr[i] | x);
ne.add(arr[i]);
for (let x of ne)
ans.add(x);
prev = ne;
}
return ans.size;
}
let n = 3;
let arr = [ 1, 2, 4 ];
document.write(distintBitwiseOR(arr, n));
</script>
|
Time Complexity: O(N*K) where N is the length of A, and K is the maximum size of elements in A.
Auxiliary Space: O(K)
Last Updated :
18 Apr, 2023
Like Article
Save Article
Share your thoughts in the comments
Please Login to comment...