给定正整数数组。任务是找到最小子集的大小,以使该集合的按位或为最大可能值。
例子:
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
资料来源:Sprinklr在校园实习
对某个值与某个数字进行按位“或”运算不会减小其值。它要么保持值不变,要么增加值。如果我们仔细研究这个问题,我们会注意到,我们可以通过对所有数组元素进行按位“或”运算来获得最大OR值。但这包括所有元素,在这里想知道最小的子集。因此,我们执行以下操作。
我)找到所有数组元素的按位或。这是我们正在寻找的OR。
II)现在,我们需要找到具有此按位OR的最小子集。这个问题类似于子集和问题,我们可以通过两种方式解决它:
- 我们递归地生成所有子集,并在给定OR的情况下返回最小的子集
- 我们使用动态编程来解决该问题。该解决方案将非常类似于具有给定总和的“最大大小”子集
递归解决方案的时间复杂度为O(2 n ),动态编程解决方案的时间复杂度为O(OR * n),其中OR为所有数组元素的OR,n为输入数组的大小。
使用方法1 :(递归生成所有子集,并在给定OR下返回最小大小)
C++
// CPP Code for above approach
#include
using namespace std;
// Compute bitwise or of all elements
// in array of size sz
int OR(int data[], int sz)
{
int mOR = 0;
for (int i = 0; i < sz; ++i) {
mOR |= data[i];
}
return mOR;
}
// Recursively calculating the size of
// minimum subset with maximum or
void minSubset(int data[], int sz, int pos, int len,
int subset[], int req, int& ans)
{
// checking the conditions for maxOR in the
// resultant subset and setting len strictly
// above 0
if (pos == sz && OR(subset, len) == req &&
len > 0)
{
ans = min(len, ans);
}
else if (pos < sz)
{
// Try the current element in the subset.
subset[len] = data[pos];
minSubset(data, sz, pos + 1, len + 1, subset,
req, ans);
// Skip the current element.
minSubset(data, sz, pos + 1, len, subset,
req, ans);
}
}
// Driver code
int main()
{
int data[] = { 5, 1, 3, 4, 2 };
int sz = sizeof(data) / sizeof(0);
int req = OR(data, sz);
int ans = sz;
// Creating a temporary subset with
// all elements 0
int subset[sz];
// Function Call
minSubset(data, sz, 0, 0, subset, req, ans);
cout << ans;
}
// Code contibuted by Adhiraj Singh
Java
// Java Program for above approach
import 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 contibuted by Abdelaziz EROUI
输出
2
时间复杂度: O(2 n )