Size of the smallest subset with maximum Bitwise OR

28 Jun, 2022
Given an array of positive integers. The task is to find the size of the smallest subset such that the Bitwise OR of that set is Maximum possible. 
Examples: 
Input : arr[] = {5, 1, 3, 4, 2}
Output : 2
7 is the maximum value possible of OR, 
5|2 = 7 and 5|3 = 7

Input : arr[] = {2, 6, 2, 8, 4, 5}
Output : 3
15 is the maximum value of OR and set
elements are 8, 6, 5 
Source: Sprinklr on Campus Internship 
Doing bitwise OR of a number with some value does not decrease its value. It either keeps the value same or increases. If we take a closer look at the problem we can notice that the maximum OR value that we can get is by doing bitwise OR of all array elements. But this includes all elements and here want to know the smallest subset. So we do the following. I) Find bitwise OR of all array elements. This is the OR we are looking for. II) Now we need to find the smallest subset with this bitwise OR. This problem is similar to the subset-sum problem, We can solve it in two ways : 
We generate all subsets and return the smallest size with given ORWe use Dynamic Programming to solve the problem. This solution is going to be very similar to Maximum size subset with given sum
We generate all subsets and return the smallest size with given OR
We use Dynamic Programming to solve the problem. This solution is going to be very similar to Maximum size subset with given sum
The time complexity of the 1st solution is O(2n) and time complexity of the Dynamic Programming solution is O(OR * n) where OR is OR of all array elements and n is the size of the input array. 
Using Method 1 : (generating all subsets and return the smallest size with given OR) 
C++
Java
Python3
C#
Javascript
// CPP Code for above approach#include <bits/stdc++.h>using namespace std; // Compute bitwise or of all elements// in array of size szint OR(int data[], int sz){    int mOR = 0;      for (int i = 0; i < sz; ++i) {        mOR |= data[i];    }         return mOR;} // calculate the size of// minimum subset with maximum orint minSubset(int data[], int sz,int maxOR){  // store the minimum size of  // the subset with maximum OR      int minSZ=sz;         // generates all subsets    for(int mask=0;mask<(1<<sz);mask++)    {      // stores the size of the current subset      int curSZ=0;      // stores the OR of all the elements      // in the current subset      int curOR=0;              for(int i=0;i<sz;i++)      {        if(mask&(1<<i))        {          curSZ++;          curOR|=data[i];        }      }      if(curOR==maxOR)        minSZ=min(minSZ,curSZ);    }     return minSZ;} // Driver codeint main(){    int data[] = { 5, 1, 3, 4, 2 };    int sz = sizeof(data) / sizeof(0);    int maxOR = OR(data, sz);         // Function Call    cout << minSubset(data, sz,maxOR) << '\n' ;}
// Java Program for above approachimport java.io.*;import java.util.*; class Solution{     // Compute bitwise or of all elements  // in array of size sz  private static int OR(int[] arr)  {    int mOR = 0;    for (int i = 0; i < arr.length; ++i)    {      mOR |= arr[i];    }    return mOR;  }     // Recursively calculating the size of  // minimum subset with maximum or  private static int maxSubset(int[] arr, int i,                int curOr, int curSize, int maxOr)  {           // If i is arr.length    if (i == arr.length)    {             // If curOr is equal to maxOr      if (curOr == maxOr)      {          return curSize;      }             // Return arr.length      else      {          return arr.length;      }    }         // Try the current element in the subset    int take = maxSubset(arr, i + 1, curOr |                          arr[i], curSize + 1, maxOr);         // Skip the current element    int notTake = maxSubset(arr, i + 1, curOr,                                      curSize, maxOr);              // Return minimum of take and notTake    return Math.min(take, notTake);  }     // Driver Code  public static void main(String[] args)  {    int[] data = {5, 1, 3, 4, 2};         int maxOr = OR(data);         // Function Call    int maxSubsetSize = maxSubset(data, 0, 0, 0, maxOr);    System.out.println(maxSubsetSize);  }} // Code contributed by Abdelaziz EROUI
# Python3 Code for above approach  # Compute bitwise or of all elements# in array of size szdef OR(data, sz):    mOR = 0    for i in range(sz) :        mOR |= data[i]            return mOR  # calculate the size of# minimum subset with maximum ordef minSubset(data, sz,maxOR):  # store the minimum size of  # the subset with maximum OR    minSZ=sz       # generates all subsets    for mask in range(1<<sz):        # stores the size of the current subset        curSZ=0        # stores the OR of all the elements        # in the current subset        curOR=0         for i in range(sz):            if(mask&(1<<i)):                curSZ+=1                curOR|=data[i]                        if(curOR==maxOR):            minSZ=min(minSZ,curSZ)                 return minSZ  # Driver codeif __name__ == '__main__':    data =[5, 1, 3, 4, 2]    sz = len(data)    maxOR = OR(data, sz)         # Function Call    print(minSubset(data, sz,maxOR))
// C# Program for above approachusing System;class Solution{     // Compute bitwise or of all elements  // in array of size sz  private static int OR(int[] arr)  {    int mOR = 0;    for (int i = 0; i < arr.Length; ++i)    {      mOR |= arr[i];    }    return mOR;  }     // Recursively calculating the size of  // minimum subset with maximum or  private static int maxSubset(int[] arr, int i,                int curOr, int curSize, int maxOr)  {           // If i is arr.length    if (i == arr.Length)    {             // If curOr is equal to maxOr      if (curOr == maxOr)      {          return curSize;      }             // Return arr.length      else      {          return arr.Length;      }    }         // Try the current element in the subset    int take = maxSubset(arr, i + 1, curOr |                          arr[i], curSize + 1, maxOr);         // Skip the current element    int notTake = maxSubset(arr, i + 1, curOr,                                      curSize, maxOr);              // Return minimum of take and notTake    return Math.Min(take, notTake);  }     // Driver Code  static void Main()  {    int[] data = {5, 1, 3, 4, 2};         int maxOr = OR(data);         // Function Call    int maxSubsetSize = maxSubset(data, 0, 0, 0, maxOr);     Console.WriteLine(maxSubsetSize);  }} // This code is contributed by SoumikMondal
<script> // JavaScript Program for above approach // Compute bitwise or of all elements  // in array of size szfunction OR(arr){    let mOR = 0;    for (let i = 0; i < arr.length; ++i)    {      mOR |= arr[i];    }    return mOR;} // Recursively calculating the size of  // minimum subset with maximum orfunction maxSubset(arr,i,curOr,curSize,maxOr){    // If i is arr.length    if (i == arr.length)    {              // If curOr is equal to maxOr      if (curOr == maxOr)      {          return curSize;      }              // Return arr.length      else      {          return arr.length;      }    }          // Try the current element in the subset    let take = maxSubset(arr, i + 1, curOr |                          arr[i], curSize + 1, maxOr);          // Skip the current element    let notTake = maxSubset(arr, i + 1, curOr,                                      curSize, maxOr);                // Return minimum of take and notTake    return Math.min(take, notTake);} // Driver Codelet data=[5, 1, 3, 4, 2];let maxOr = OR(data); // Function Calllet maxSubsetSize = maxSubset(data, 0, 0, 0, maxOr);document.write(maxSubsetSize);          // This code is contributed by rag2127 </script>
2
Time complexity: O(2n)Auxiliary Space: O(n) 
Using Method 2: 
 We first find the OR of all elements of given array.Now we need to find the smallest subset with this bitwise OR.
To do so, use the similar DP approach as given in the subset sum problem. count[i][j] denotes the minimum size subset till ith element whose OR is j.
C++
Java
Python3
Javascript
// CPP Code for above approach#include <bits/stdc++.h>using namespace std; // Compute bitwise or of all elements// in array of size szint OR(int data[], int sz){    int mOR = 0;    for (int i = 0; i < sz; ++i) {        mOR |= data[i];    }     return mOR;} // calculate the size of// minimum subset with maximum orint minSubset(int data[], int sz, int maxOR){    // count table where      // count[i][j] => minimum size subset till ith element      // whose OR is j    vector<vector<int> > count(sz + 1, vector<int>(maxOR + 1, 1e9));       count[0][0] = 0;     for (int i = 0; i < sz; i++) {        for (int j = 0; j <= maxOR; j++) {            // Do not consider ith element.            count[i + 1][j] = min(count[i + 1][j], count[i][j]);             // Consider the ith element.            if (count[i][j] != 1e9) {                count[i + 1][j | data[i]] = min(                    count[i + 1][j | data[i]], count[i][j] + 1);            }        }    }     return count[sz][maxOR];} // Driver codeint main(){    int data[] = { 5, 1, 3, 4, 2 };    int sz = sizeof(data) / sizeof(0);    int maxOR = OR(data, sz);     // Function Call    cout << minSubset(data, sz, maxOR) << '\n';}
/*package whatever //do not write package name here */ import java.io.*;import java.util.*; class GFG {  // Java Code for above approach   // Compute bitwise or of all elements  // in array of size sz  static int OR(int data[], int sz)  {    int mOR = 0;    for (int i = 0; i < sz; ++i) {      mOR |= data[i];    }     return mOR;  }   // calculate the size of  // minimum subset with maximum or  static int minSubset(int data[], int sz, int maxOR)  {    // count table where    // count[i][j] => minimum size subset till ith element    // whose OR is j    int count[][] = new int[sz + 1][maxOR + 1];    for(int i=0;i<sz+1;i++){      Arrays.fill(count[i],1000000000);    }     count[0][0] = 0;     for (int i = 0; i < sz; i++) {      for (int j = 0; j <= maxOR; j++) {        // Do not consider ith element.        count[i + 1][j] = Math.min(count[i + 1][j], count[i][j]);         // Consider the ith element.        if (count[i][j] != 1000000000) {          count[i + 1][j | data[i]] = Math.min(            count[i + 1][j | data[i]], count[i][j] + 1);        }      }    }     return count[sz][maxOR];  }   /* Driver program to test above function*/  public static void main(String args[])  {    int data[] = { 5, 1, 3, 4, 2 };    int sz = data.length;    int maxOR = OR(data, sz);     // Function Call    System.out.println(minSubset(data, sz, maxOR));  }} // This code is contributed by shinjanpatra.
# Python3 Code for above approach  # Compute bitwise or of all elements# in array of size szdef OR(data, sz):    mOR = 0    for i in range(sz):        mOR |= data[i]    return mOR  # calculate the size of# minimum subset with maximum ordef minSubset(data, sz, maxOR):    # count table where      # count[i][j] => minimum size subset till ith element      # whose OR is j    count=[[1e9 for _ in range(maxOR+1)]for _ in range(sz+1)]       count[0][0] = 0     for i in range(sz) :        for j in range(maxOR) :            # Do not consider ith element.            count[i + 1][j] = min(count[i + 1][j], count[i][j])             # Consider the ith element.            if (count[i][j] != 1e9) :                count[i + 1][j | data[i]] = min(                    count[i + 1][j | data[i]], count[i][j] + 1)                                return count[sz][maxOR]  # Driver codeif __name__ == '__main__':    data = [5, 1, 3, 4, 2]    sz = len(data)    maxOR = OR(data, sz)     # Function Call    print(minSubset(data, sz, maxOR))
<script> // JavaScript Code for above approach // Compute bitwise or of all elements// in array of size szfunction OR(data, sz){    let mOR = 0    for(let i=0;i<sz;i++)        mOR |= data[i]    return mOR} // calculate the size of// minimum subset with maximum orfunction minSubset(data, sz, maxOR){    // count table where    // count[i][j] => minimum size subset till ith element    // whose OR is j    let count = new Array(sz+1).fill(0).map(()=>new Array(maxOR+1).fill(1e9));     count[0][0] = 0     for(let i=0;i<sz;i++){        for(let j=0;j<maxOR;j++){            // Do not consider ith element.            count[i + 1][j] = Math.min(count[i + 1][j], count[i][j])             // Consider the ith element.            if (count[i][j] != 1e9)                count[i + 1][j | data[i]] = Math.min(                    count[i + 1][j | data[i]], count[i][j] + 1)        }    }                return count[sz][maxOR]} // Driver code let data = [5, 1, 3, 4, 2]let sz = data.lengthlet maxOR = OR(data, sz) // Function Calldocument.write(minSubset(data, sz, maxOR),"</br>") // This code is contributed by shinjanpatra </script>
2
Time complexity: O(n*maxOR) where n is the size of the array and maxOR is the maximum or that can be obtained.Auxiliary Space: O(n*maxOR) 
Sach_Code
ankthon
SURENDRA_GANGWAR
ukasp
singhadhiraj001
AbdelazizEroui
SoumikMondal
rag2127
pankajsharmagfg
kk773572498
ashutoshsinghgeeksforgeeks
amartyaghoshgfg
shinjanpatra
Bitwise-OR
Sprinklr
subset
Algorithms
Arrays
Dynamic Programming
Sprinklr
Arrays
Dynamic Programming
subset
Algorithms
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.