📜  所有子矩阵的按位或运算

📅  最后修改于: 2021-06-25 14:38:24             🧑  作者: Mango

给定一个NxN矩阵,任务是找到其所有矩形子矩阵的按位或的总和。

例子:

Input : arr[][] = {{1, 0, 0},
                   {0, 0, 0},
                   {0, 0, 0}}
Output : 9
Explanation: All the submatrices starting from 
the index (0, 0) will have OR value as 1.
Thus, ans = 9

Input : arr[][] = {{9, 7, 4},
                    {8, 9, 2},
                    {11, 11, 5}}
Output : 398

先决条件:OR值为1的子矩阵的数量

简单解决方案:一个简单的解决方案是生成所有子矩阵,并为每个子矩阵找到所需的OR值。该方法的时间复杂度将为O(N 6 )。

高效的解决方案:为了更好地理解,我们假定元素的任何位都由变量’i’表示,并且变量’sum’用于存储最终和。

这里的想法是,我们将尝试找到设置有i位的OR值(按位或(|)的子矩阵)的数量。让我们假设,有i位设置的S i个子矩阵。对于,i位,总和可以更新为总和+ =(2 i * S i )。

对于每个位“ i”,如果设置了arr [R] [C]的i位,则创建一个布尔矩阵set_bit ,将其存储在索引(R,C)处为“ 1”。否则,它存储为“ 0”。然后,对于此布尔数组,我们尝试找到OR值为1(S i )的矩形子矩阵的数量。因为,第i位,最后一笔将被更新为:

sum += 2i * Si

下面是上述方法的实现:

C++
// C++ program to find sum of Bitwise-OR of
// all submatrices
  
#include 
#include 
  
using namespace std;
  
#define n 3
  
// Function to find prefix-count for each row
// from right to left
void findPrefixCount(int p_arr[][n], bool set_bit[][n])
{
    for (int i = 0; i < n; i++) 
    {
        for (int j = n - 1; j >= 0; j--) 
        {
            if (set_bit[i][j])
                continue;
  
            if (j != n - 1)
                p_arr[i][j] += p_arr[i][j + 1];
  
            p_arr[i][j] += (int)(!set_bit[i][j]);
        }
    }
}
  
// Function to create a boolean matrix set_bit which
// stores ‘1’ at an index (R, C) if ith bit
// of arr[R][C] is set.
int matrixOrValueOne(bool set_bit[][n])
{
    // array to store prefix count of zeros from
    // right to left for boolean array
    int p_arr[n][n] = { 0 };
  
    findPrefixCount(p_arr, set_bit);
  
    // variable to store the count of
    // submatrices with OR value 0
    int count_zero_submatrices = 0;
  
    // For each index of a column we will try to
    // determine the number of sub-matrices
    // starting from that index
    // and has all 1s
    for (int j = 0; j < n; j++) 
    {
        int i = n - 1;
  
        // stack to store elements and the count
        // of the numbers they popped
        // First part of pair will be the
        // value of inserted element.
        // Second part will be the count
        // of the number of elements pushed
        // before with a greater value
        stack > q;
  
        // variable to store the number of submatrices
        // with all 0s
        int to_sum = 0;
        while (i >= 0) 
        {
            int c = 0;
  
            while (q.size() != 0 and q.top().first > p_arr[i][j]) 
            {
                to_sum -= (q.top().second + 1) * 
                             (q.top().first - p_arr[i][j]);
                c += q.top().second + 1;
                q.pop();
            }
  
            to_sum += p_arr[i][j];
            count_zero_submatrices += to_sum;
            q.push({ p_arr[i][j], c });
  
            i--;
        }
    }
  
    return (n * (n + 1) * n * (n + 1)) / 
                    4 - count_zero_submatrices;
}
  
// Function to find sum of Bitwise-OR of
// all submatrices
int sumOrMatrix(int arr[][n])
{
    int sum = 0;
  
    int mul = 1;
  
    for (int i = 0; i < 30; i++) 
    {
        // matrix to store the status
        // of ith bit of each element
        // of matrix arr
        bool set_bit[n][n];
  
        for (int R = 0; R < n; R++)
            for (int C = 0; C < n; C++)
                set_bit[R][C] = ((arr[R][C] & (1 << i)) != 0);
  
        sum += (mul * matrixOrValueOne(set_bit));
  
        mul *= 2;
    }
  
    return sum;
}
  
// Driver Code
int main()
{
    int arr[][n] = { { 9, 7, 4 },
                     { 8, 9, 2 },
                     { 11, 11, 5 } };
  
    cout << sumOrMatrix(arr);
  
    return 0;
}


Java
// Java program to find sum of Bitwise-OR of 
// all submatrices 
import java.util.*;
  
class GFG
{
  
static int n = 3; 
  
// Function to find prefix-count for  
// each row from right to left 
static void findPrefixCount(int p_arr[][],
                        boolean set_bit[][]) 
{ 
    for (int i = 0; i < n; i++) 
    { 
        for (int j = n - 1; j >= 0; j--) 
        { 
            if (set_bit[i][j]) 
                continue; 
  
            if (j != n - 1) 
                p_arr[i][j] += p_arr[i][j + 1]; 
  
            p_arr[i][j] += (!set_bit[i][j]) ? 1 : 0; 
        } 
    } 
} 
  
static class pair
{
    int first,second;
    pair(){}
      
    pair(int a,int b)
    {
        first = a; 
        second = b;
    }
}
  
// Function to create a booleanean
// matrix set_bit which stores '1' 
// at an index (R, C) if ith bit 
// of arr[R][C] is set. 
static int matrixOrValueOne(boolean set_bit[][]) 
{ 
    // array to store prefix count of zeros from 
    // right to left for booleanean array 
    int p_arr[][] = new int[n][n] ;
      
    for(int i = 0; i < n; i++)
    for(int j = 0; j < n; j++)
    p_arr[i][j] = 0;
  
    findPrefixCount(p_arr, set_bit); 
  
    // variable to store the count of 
    // submatrices with OR value 0 
    int count_zero_submatrices = 0; 
  
    // For each index of a column we will try to 
    // determine the number of sub-matrices 
    // starting from that index 
    // and has all 1s 
    for (int j = 0; j < n; j++) 
    { 
        int i = n - 1; 
  
        // stack to store elements and the count 
        // of the numbers they popped 
        // First part of pair will be the 
        // value of inserted element. 
        // Second part will be the count 
        // of the number of elements pushed 
        // before with a greater value 
        Stack q = new Stack(); 
  
        // variable to store the number of submatrices 
        // with all 0s 
        int to_sum = 0; 
        while (i >= 0) 
        { 
            int c = 0; 
  
            while (q.size() != 0 && q.peek().first > p_arr[i][j]) 
            { 
                to_sum -= (q.peek().second + 1) * 
                            (q.peek().first - p_arr[i][j]); 
                c += q.peek().second + 1; 
                q.pop(); 
            } 
  
            to_sum += p_arr[i][j]; 
            count_zero_submatrices += to_sum; 
            q.push(new pair( p_arr[i][j], c )); 
  
            i--; 
        } 
    } 
  
    return (n * (n + 1) * n * (n + 1)) / 
                4 - count_zero_submatrices; 
} 
  
// Function to find sum of Bitwise-OR of 
// all submatrices 
static int sumOrMatrix(int arr[][]) 
{ 
    int sum = 0; 
  
    int mul = 1; 
  
    for (int i = 0; i < 30; i++) 
    { 
        // matrix to store the status 
        // of ith bit of each element 
        // of matrix arr 
        boolean set_bit[][] = new boolean[n][n]; 
  
        for (int R = 0; R < n; R++) 
            for (int C = 0; C < n; C++) 
                set_bit[R][C] = ((arr[R][C] & (1 << i)) != 0); 
  
        sum += (mul * matrixOrValueOne(set_bit)); 
  
        mul *= 2; 
    } 
  
    return sum; 
} 
  
// Driver Code 
public static void main(String args[])
{ 
    int arr[][] = { { 9, 7, 4 }, 
                    { 8, 9, 2 }, 
                    { 11, 11, 5 } }; 
  
    System.out.println( sumOrMatrix(arr)); 
} 
}
  
// This code is contributed by Arnab Kundu


Python3
# Python3 program to find sum of 
# Bitwise-OR of all submatrices 
  
# Function to find prefix-count for 
# each row from right to left 
def findPrefixCount(p_arr, set_bit): 
  
    for i in range(0, n):
        for j in range(n - 1, -1, -1): 
  
            if set_bit[i][j]: 
                continue
            if j != n - 1: 
                p_arr[i][j] += p_arr[i][j + 1] 
  
            p_arr[i][j] += int(not set_bit[i][j]) 
  
# Function to create a boolean matrix 
# set_bit which stores ‘1’ at an index 
# (R, C) if ith bit of arr[R][C] is set. 
def matrixOrValueOne(arr): 
  
    # Array to store prefix count of zeros 
    # from right to left for boolean array 
    p_arr = [[0 for i in range(n)] 
                for j in range(n)] 
  
    findPrefixCount(p_arr, arr) 
  
    # Variable to store the count of 
    # submatrices with OR value 0 
    count_zero_submatrices = 0
  
    # Loop to evaluate each column of 
    # the prefix matrix uniquely. 
    # For each index of a column we will try 
    # to determine the number of sub-matrices 
    # starting from that index and has all 1s 
    for j in range(0, n): 
  
        i = n - 1
          
        # stack to store elements and the 
        # count of the numbers they popped 
  
        # First part of pair will be the 
        # value of inserted element. 
        # Second part will be the count 
        # of the number of elements pushed 
        # before with a greater value 
        q = [] 
  
        # Variable to store the number 
        # of submatrices with all 0s 
        to_sum = 0
          
        while i >= 0: 
  
            c = 0
            while (len(q) != 0 and 
                   q[-1][0] > p_arr[i][j]): 
  
                to_sum -= ((q[-1][1] + 1) *
                           (q[-1][0] - p_arr[i][j])) 
  
                c += q.pop()[1] + 1
  
            to_sum += p_arr[i][j] 
            count_zero_submatrices += to_sum 
  
            q.append((p_arr[i][j], c)) 
            i -= 1
  
    # Return the final answer 
    return ((n * (n + 1) * n * (n + 1)) //
             4 - count_zero_submatrices) 
  
# Function to find sum of 
# Bitwise-OR of all submatrices 
def sumOrMatrix(arr): 
  
    Sum, mul = 0, 1
    for i in range(0, 30): 
      
        # matrix to store the status 
        # of ith bit of each element 
        # of matrix arr 
        set_bit = [[False for i in range(n)] 
                          for j in range(n)]
  
        for R in range(0, n): 
            for C in range(0, n): 
                set_bit[R][C] = ((arr[R][C] & 
                                 (1 << i)) != 0) 
  
        Sum += (mul * matrixOrValueOne(set_bit)) 
        mul *= 2
  
    return Sum
  
# Driver Code 
if __name__ == "__main__":
      
    n = 3
    arr = [[9, 7, 4], 
        [8, 9, 2], 
        [11, 11, 5]] 
  
    print(sumOrMatrix(arr)) 
  
# This code is contributed by Rituraj Jain


C#
// C# program to find sum of Bitwise-OR of 
// all submatrices 
using System;
using System.Collections.Generic; 
  
class GFG
{
static int n = 3; 
  
// Function to find prefix-count for 
// each row from right to left 
static void findPrefixCount(int [,]p_arr,
                            Boolean [,]set_bit) 
{ 
    for (int i = 0; i < n; i++) 
    { 
        for (int j = n - 1; j >= 0; j--) 
        { 
            if (set_bit[i, j]) 
                continue; 
  
            if (j != n - 1) 
                p_arr[i, j] += p_arr[i, j + 1]; 
  
            p_arr[i, j] += (!set_bit[i, j]) ? 1 : 0; 
        } 
    } 
} 
  
public class pair
{
    public int first,second;
    public pair(){}
      
    public pair(int a, int b)
    {
        first = a; 
        second = b;
    }
}
  
// Function to create a booleanean
// matrix set_bit which stores '1' 
// at an index (R, C) if ith bit 
// of arr[R,C] is set. 
static int matrixOrValueOne(Boolean [,]set_bit) 
{ 
    // array to store prefix count of zeros from 
    // right to left for booleanean array 
    int [,]p_arr = new int[n, n];
      
    for(int i = 0; i < n; i++)
    for(int j = 0; j < n; j++)
    p_arr[i, j] = 0;
  
    findPrefixCount(p_arr, set_bit); 
  
    // variable to store the count of 
    // submatrices with OR value 0 
    int count_zero_submatrices = 0; 
  
    // For each index of a column we will try to 
    // determine the number of sub-matrices 
    // starting from that index 
    // and has all 1s 
    for (int j = 0; j < n; j++) 
    { 
        int i = n - 1; 
  
        // stack to store elements and the count 
        // of the numbers they popped 
        // First part of pair will be the 
        // value of inserted element. 
        // Second part will be the count 
        // of the number of elements pushed 
        // before with a greater value 
        Stack q = new Stack(); 
  
        // variable to store the number of 
        // submatrices with all 0s 
        int to_sum = 0; 
        while (i >= 0) 
        { 
            int c = 0; 
  
            while (q.Count != 0 &&
                   q.Peek().first > p_arr[i, j]) 
            { 
                to_sum -= (q.Peek().second + 1) * 
                          (q.Peek().first - p_arr[i, j]); 
                c += q.Peek().second + 1; 
                q.Pop(); 
            } 
  
            to_sum += p_arr[i, j]; 
            count_zero_submatrices += to_sum; 
            q.Push(new pair(p_arr[i, j], c)); 
  
            i--; 
        } 
    } 
  
    return (n * (n + 1) * n * (n + 1)) / 
            4 - count_zero_submatrices; 
} 
  
// Function to find sum of Bitwise-OR of 
// all submatrices 
static int sumOrMatrix(int [,]arr) 
{ 
    int sum = 0; 
  
    int mul = 1; 
  
    for (int i = 0; i < 30; i++) 
    { 
        // matrix to store the status 
        // of ith bit of each element 
        // of matrix arr 
        Boolean [,]set_bit = new Boolean[n, n]; 
  
        for (int R = 0; R < n; R++) 
            for (int C = 0; C < n; C++) 
                set_bit[R, C] = ((arr[R, C] & 
                                 (1 << i)) != 0); 
  
        sum += (mul * matrixOrValueOne(set_bit)); 
  
        mul *= 2; 
    } 
  
    return sum; 
} 
  
// Driver Code 
public static void Main(String []args)
{ 
    int [,]arr = {{ 9, 7, 4 }, 
                  { 8, 9, 2 }, 
                  { 11, 11, 5 }}; 
  
    Console.WriteLine( sumOrMatrix(arr)); 
} 
}
  
// This code is contributed by Rajput-Ji


输出:
398

时间复杂度:O(N 2 )。