给定一个正整数数组。任务是找到最小子集的大小,使得该集合的按位 OR是最大可能的。
例子:
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 来实现的。但这包括所有元素,这里想知道最小的子集。因此,我们执行以下操作。
I) 查找所有数组元素的按位或。这就是我们正在寻找的 OR。
II) 现在我们需要用这个按位或找到最小的子集。这个问题类似于子集和问题,我们可以通过两种方式解决它:
- 我们递归地生成所有子集并返回给定 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
C#
// C# Program for above approach
using 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 contibuted by SoumikMondal
Javascript
输出
2
时间复杂度: O(2 n )
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。