Given two arrays A and B of length N, find the maximum length of a common interval of A and B such that the bitwise OR of the elements in the interval of A is equal to the bitwise AND of the elements in the interval of B.
Formally, given the indices i and j (0 ? i ? j < N), find the maximum value of j-i+1 such that: (A[i] OR A[i+1] OR … OR A[j]) = (B[i] AND B[i+1] AND … AND B[j])
Examples:
Input: A[] = {2, 1, 3, 3}, B[] = {15, 3, 7, 11}
Output: 4
Explanation: OR(2, 1) = AND(15, 3), Length = 2,
OR(2, 1, 3, ) = AND(15, 3, 7), Length = 3,
OR(2, 1, 3, 3) = AND(15, 3, 7, 11), Length = 4,
OR(1, 3) = AND(3, 7), Length = 2,
OR(1, 3, 3) = AND(3, 7, 11), Length = 3, and so on. Hence, the largest length is 4.Input: A[] = {1, 2, 3, 4}, B[] = {4, 3, 7, 11}
Output: 2
Explanation: OR(2, 3) = AND(3, 7), Length = 2, The largest subarray length is 2.
Approach: The given problem can be solved based on the following observation followed by the binary search:
- Bitwise AND will decrease or remain the same by continuously taking AND with elements.
- Whereas Bitwise OR will increase or remain the same by continuously taking OR with elements.
These above properties will create monotonicity so we can use binary search to calculate the largest length.
Follow the steps below to solve the problem:
- Create a 2D prefix sum array for every bit for both arrays. With this pre-computation, we can calculate bitwise OR and AND in nearly constant time.
- Then, for every index, we use binary search where low is equal to zero and high will be the length from index i to the last index.
- If OR of length mid starting with index i is less than or equal to AND of length mid, then low is set to mid otherwise high is set to mid-1.
- After calculating the largest length at each index with the above condition using binary search, we take max with ans which will be our answer.
Below is the implementation for the above approach:
// C++ implementation to find the largest length sub-array // of two arrays A and B such that bitwise-OR of A from // index i to j and bitwise-AND of array B from index i to j // are equal #include <bits/stdc++.h> using namespace std;
// function for calculating bitwise OR of length 'length' // from index i int orCalculate( int st, int length,
vector<vector< int > >& bitPrefix)
{ int val = 0;
for ( int j = 0; j < 32; j++) {
int cnt
= bitPrefix[st + length][j] - bitPrefix[st][j];
if (cnt != 0)
// If atleast one jth bit is set
// between that range, it will
// be added to val
val += (1 << j);
}
return val;
} // Function for calculating bitwise AND // of length 'length' from index i int andCalculate( int st, int length,
vector<vector< int > >& bitPrefix)
{ int val = 0;
for ( int j = 0; j < 32; j++) {
int cnt
= bitPrefix[st + length][j] - bitPrefix[st][j];
if (cnt == length)
// if jth bit is set in all
// elements of that range, it
// will be added to val
val += (1 << j);
}
return val;
} // Function for calculating largest length // sub-array of two arrays A and B such // that bitwise-OR of A from index i to j // and bitwise-AND of array B from index // i to j are equal int largestLength(vector< int >& A, vector< int >& B)
{ int N = A.size();
// Creating 2D vectors for prefix
// bit's sum for both arrays
vector<vector< int > > prefixBitSumA(N + 1,
vector< int >(32, 0)),
prefixBitSumB(N + 1, vector< int >(32, 0));
for ( int i = 0; i < N; i++) {
for ( int j = 0; j < 32; j++) {
prefixBitSumA[i + 1][j]
= ((A[i] & 1 << j) ? 1 : 0)
+ prefixBitSumA[i][j];
prefixBitSumB[i + 1][j]
= ((B[i] & 1 << j) ? 1 : 0)
+ prefixBitSumB[i][j];
}
}
// Initializing ans variable
// for storing answer
int ans = 0;
for ( int i = 0; i < N; i++) {
int low = 0, high = N - i;
// Binary search while loop
while (low < high) {
int mid = (low + high + 1) / 2;
if (orCalculate(i, mid, prefixBitSumA)
<= andCalculate(i, mid, prefixBitSumB))
low = mid;
// Condition mentioned above
else
high = mid - 1;
}
// If final result for this index
// 'low' also satisfying problem's
// condition then take max with 'ans'
// otherwise 'low' is not
// considered as result
if (orCalculate(i, low, prefixBitSumA)
== andCalculate(i, low, prefixBitSumB))
ans = max(ans, low);
}
// Final answer
return ans;
} // Driver code int main()
{ vector< int > A = { 2, 1, 3, 3 };
vector< int > B = { 15, 3, 7, 11 };
// Function Call
cout << largestLength(A, B);
return 0;
} |
// Java implementation to find the largest length sub-array // of two arrays A and B such that bitwise-OR of A from // index i to j and bitwise-AND of array B from index i to j // are equal import java.io.*;
import java.util.*;
class GFG {
// function for calculating bitwise OR of length
// 'length' from index i
static int orCalculate( int st, int length,
List<List<Integer> > bitPrefix)
{
int val = 0 ;
for ( int j = 0 ; j < 32 ; j++) {
int cnt = bitPrefix.get(st + length).get(j)
- bitPrefix.get(st).get(j);
if (cnt != 0 )
// If atleast one jth bit is set between
// that range, it will be added to val
val += ( 1 << j);
}
return val;
}
// Function for calculating bitwise AND of length
// 'length' from index i
static int andCalculate( int st, int length,
List<List<Integer> > bitPrefix)
{
int val = 0 ;
for ( int j = 0 ; j < 32 ; j++) {
int cnt = bitPrefix.get(st + length).get(j)
- bitPrefix.get(st).get(j);
if (cnt == length)
// if jth bit is set in all elements of that
// range, it will be added to val
val += ( 1 << j);
}
return val;
}
// Function for calculating largest length sub-array of
// two arrays A and B such that bitwise-OR of A from
// index i to j and bitwise-AND of array B from index i
// to j are equal
static int largestLength(List<Integer> A,
List<Integer> B)
{
int N = A.size();
// Creating 2D lists for prefix bit's sum for both
// arrays
List<List<Integer> > prefixBitSumA
= new ArrayList<>();
List<List<Integer> > prefixBitSumB
= new ArrayList<>();
for ( int i = 0 ; i <= N; i++) {
prefixBitSumA.add( new ArrayList<>(
Collections.nCopies( 32 , 0 )));
prefixBitSumB.add( new ArrayList<>(
Collections.nCopies( 32 , 0 )));
}
for ( int i = 0 ; i < N; i++) {
for ( int j = 0 ; j < 32 ; j++) {
prefixBitSumA.get(i + 1 ).set(
j, ((A.get(i) & ( 1 << j)) != 0 ? 1 : 0 )
+ prefixBitSumA.get(i).get(j));
prefixBitSumB.get(i + 1 ).set(
j, ((B.get(i) & ( 1 << j)) != 0 ? 1 : 0 )
+ prefixBitSumB.get(i).get(j));
}
}
// Initializing ans variable for storing answer
int ans = 0 ;
for ( int i = 0 ; i < N; i++) {
int low = 0 , high = N - i;
// Binary search while loop
while (low < high) {
int mid = (low + high + 1 ) / 2 ;
if (orCalculate(i, mid, prefixBitSumA)
<= andCalculate(i, mid, prefixBitSumB))
low = mid;
// Condition mentioned above
else
high = mid - 1 ;
}
// If final result for this index 'low' also
// satisfying problem's condition then take max
if (orCalculate(i, low, prefixBitSumA)
== andCalculate(i, low, prefixBitSumB)) {
ans = Math.max(ans, low);
}
}
return ans;
}
public static void main(String[] args)
{
List<Integer> A = new ArrayList<Integer>(
Arrays.asList( 2 , 1 , 3 , 3 ));
List<Integer> B = new ArrayList<Integer>(
Arrays.asList( 15 , 3 , 7 , 11 ));
System.out.println(largestLength(A, B));
}
} // This code is contributed by karthik. |
# Python implementation to find the largest length sub-array # of two arrays A and B such that bitwise-OR of A from # index i to j and bitwise-AND of array B from index i to j # are equal # Function for calculating bitwise OR of length 'length' from index i def orCalculate(st, length, bitPrefix):
val = 0
for j in range ( 32 ):
cnt = bitPrefix[st + length][j] - bitPrefix[st][j]
if cnt ! = 0 :
# If atleast one jth bit is set between that range,
# it will be added to val
val + = ( 1 << j)
return val
# Function for calculating bitwise AND of length 'length' # from index i def andCalculate(st, length, bitPrefix):
val = 0
for j in range ( 32 ):
cnt = bitPrefix[st + length][j] - bitPrefix[st][j]
if cnt = = length:
# If jth bit is set in all elements of that
# range, it will be added to val
val + = ( 1 << j)
return val
# Function for calculating largest length sub-array of # two arrays A and B such that bitwise-OR of A from index # i to j and bitwise-AND of array B from index i to j # are equal def largestLength(A, B):
N = len (A)
# Creating 2D lists for prefix bit's sum for both arrays
prefixBitSumA = [[ 0 ] * 32 for _ in range (N + 1 )]
prefixBitSumB = [[ 0 ] * 32 for _ in range (N + 1 )]
for i in range (N):
for j in range ( 32 ):
prefixBitSumA[i + 1 ][j] = ((A[i] & ( 1 << j))
! = 0 ) + prefixBitSumA[i][j]
prefixBitSumB[i + 1 ][j] = ((B[i] & ( 1 << j))
! = 0 ) + prefixBitSumB[i][j]
# Initializing ans variable for storing answer
ans = 0
for i in range (N):
low, high = 0 , N - i
# Binary search while loop
while low < high:
mid = (low + high + 1 ) / / 2
if orCalculate(i, mid, prefixBitSumA) < = andCalculate(i, mid, prefixBitSumB):
low = mid
# condition mentioned above
else :
high = mid - 1
# If final result for this index 'low' also satisfying
# problem's condition then take max
if orCalculate(i, low, prefixBitSumA) = = andCalculate(i, low, prefixBitSumB):
ans = max (ans, low)
return ans
# Driver code A = [ 2 , 1 , 3 , 3 ]
B = [ 15 , 3 , 7 , 11 ]
print (largestLength(A, B))
# This code is contributed by sankar. |
// C# implementation to find the largest length sub-array // of two arrays A and B such that bitwise-OR of A from // index i to j and bitwise-AND of array B from index i to j // are equal using System;
using System.Collections.Generic;
class Solution
{ // function for calculating bitwise OR of length 'length'
// from index i
static int orCalculate( int st, int length,
List<List< int >> bitPrefix)
{
int val = 0;
for ( int j = 0; j < 32; j++)
{
int cnt = bitPrefix[st + length][j] - bitPrefix[st][j];
if (cnt != 0)
// If atleast one jth bit is set
// between that range, it will
// be added to val
val += (1 << j);
}
return val;
}
// Function for calculating bitwise AND
// of length 'length' from index i
static int andCalculate( int st, int length,
List<List< int >> bitPrefix)
{
int val = 0;
for ( int j = 0; j < 32; j++)
{
int cnt = bitPrefix[st + length][j] - bitPrefix[st][j];
if (cnt == length)
// if jth bit is set in all
// elements of that range, it
// will be added to val
val += (1 << j);
}
return val;
}
// Function for calculating largest length
// sub-array of two arrays A and B such
// that bitwise-OR of A from index i to j
// and bitwise-AND of array B from index
// i to j are equal
static int largestLength(List< int > A, List< int > B)
{
int N = A.Count;
// Creating 2D lists for prefix
// bit's sum for both arrays
List<List< int >> prefixBitSumA = new List<List< int >>(N + 1);
List<List< int >> prefixBitSumB = new List<List< int >>(N + 1);
for ( int i = 0; i <= N; i++)
{
prefixBitSumA.Add( new List< int >( new int [32]));
prefixBitSumB.Add( new List< int >( new int [32]));
}
for ( int i = 0; i < N; i++)
{
for ( int j = 0; j < 32; j++)
{
prefixBitSumA[i + 1][j] = ((A[i] & (1 << j)) != 0 ? 1 : 0) + prefixBitSumA[i][j];
prefixBitSumB[i + 1][j] = ((B[i] & (1 << j)) != 0 ? 1 : 0) + prefixBitSumB[i][j];
}
}
// Initializing ans variable
// for storing answer
int ans = 0;
for ( int i = 0; i < N; i++)
{
int low = 0, high = N - i;
// Binary search while loop
while (low < high)
{
int mid = (low + high + 1) / 2;
if (orCalculate(i, mid, prefixBitSumA) <= andCalculate(i, mid, prefixBitSumB))
low = mid;
// Condition mentioned above
else
high = mid - 1;
}
// If final result for this index
// 'low' also satisfying problem's
// condition then take max
if (orCalculate(i, low, prefixBitSumA) == andCalculate(i, low, prefixBitSumB)) {
ans = Math.Max(ans, low);
}
}
return ans;
}
// Driver's code
static void Main() {
List< int > A = new List< int >{ 2, 1, 3, 3 };
List< int > B = new List< int >{ 15, 3, 7, 11 };
Console.WriteLine(largestLength(A, B));
}
} |
// JavaScript implementation to find // the largest length sub-array of // two arrays A and B such that bitwise-OR // of A from index i to j and bitwise-AND // of array B from index i to j are equal // Function for calculating bitwise OR of length 'length' from index i function orCalculate(st, length, bitPrefix) {
let val = 0;
for (let j = 0; j < 32; j++) {
let cnt = bitPrefix[st+length][j] - bitPrefix[st][j];
if (cnt != 0)
{
// If atleast one jth bit is set between that range,
// it will be added to val
val += (1 << j);
}
}
return val;
} // Function for calculating bitwise AND of length 'length' from index i function andCalculate(st, length, bitPrefix) {
let val = 0;
for (let j = 0; j < 32; j++) {
let cnt = bitPrefix[st+length][j] - bitPrefix[st][j];
if (cnt == length)
{
// If jth bit is set in all elements of that
// range, it will be added to val
val += (1 << j);
}
}
return val;
} // Function for calculating largest length sub-array of // two arrays A and B such that bitwise-OR of A from index // i to j and bitwise-AND of array B from index i to j // are equal function largestLength(A, B) {
let N = A.length;
// Creating 2D lists for prefix bit's sum for both arrays
let prefixBitSumA = Array(N + 1).fill().map(() => Array(32).fill(0));
let prefixBitSumB = Array(N + 1).fill().map(() => Array(32).fill(0));
for (let i = 0; i < N; i++) {
for (let j = 0; j < 32; j++) {
prefixBitSumA[i+1][j] = ((A[i] & (1 << j)) != 0) + prefixBitSumA[i][j];
prefixBitSumB[i+1][j] = ((B[i] & (1 << j)) != 0) + prefixBitSumB[i][j];
}
}
// Initializing ans variable for storing answer
let ans = 0;
for (let i = 0; i < N; i++) {
let low = 0, high = N-i;
// Binary search while loop
while (low < high) {
let mid = Math.floor((low + high + 1) / 2);
if (orCalculate(i, mid, prefixBitSumA) <= andCalculate(i, mid, prefixBitSumB)) {
low = mid;
}
// condition mentioned above
else {
high = mid - 1;
}
}
// If final result for this index 'low' also satisfying
// problem's condition then take max
if (orCalculate(i, low, prefixBitSumA) == andCalculate(i, low, prefixBitSumB)) {
ans = Math.max(ans, low);
}
}
return ans;
} // Driver code let A = [2, 1, 3, 3]; let B = [15, 3, 7, 11]; console.log(largestLength(A, B)); // This code is contributed by akashish__. |
4
Time Complexity: O(N*logN), where N is the length of the array (logN for binary search for each index),
Auxiliary Space: O(N), O(N*32*2) for 2D prefixBitArray equal to O(N).