Open In App

Max length of common interval whose Bitwise OR, AND are equal in both Arrays

Last Updated : 28 Mar, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

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++




// 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




// 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.


Python3




# 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#




// 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




// 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__.


Output

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).



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads