📜  最大化 NxN 网格中 KxK 子网格的中值

📅  最后修改于: 2021-10-26 05:11:24             🧑  作者: Mango

给定一个由非负整数和整数K组成的大小为N 的方阵arr[][] ,任务是找到大小为K的方阵子矩阵的元素的最大中值。

例子:

朴素方法:解决上述给定问题的最简单方法是迭代每个大小为K*K 的子矩阵,然后在形成的所有子矩阵中找到最大中值。

时间复杂度: O(N 2 * K 2 )
辅助空间: O(1)

高效方法:上述问题可以基于以下观察进行优化:

  • 如果M是方形子矩阵的中值,则该子矩阵中小于或等于M的数字的计数必须小于(K 2 +1)/2
  • 这个想法是使用二分搜索来找到给定的中值:
    • 如果大小为K×K 的任何子矩阵中小于M的数字计数小于(K 2 +1)/2,则增加左边界。
    • 否则,递减右边界。
  • 这个想法是使用矩阵的前缀和来计算方形子矩阵中恒定时间内小于特定值的元素。

请按照以下步骤解决问题:

  • 初始化两个变量,0INT_MAX,表示搜索空间的范围。
  • 迭代直到小于并执行以下步骤:
    • 找到范围[low, high]的中间值并将其存储在一个变量中,比如mid
    • 初始化向量的向量说Pre以在前缀子矩阵中存储小于或等于mid的元素计数。
    • 使用变量ij迭代矩阵arr[][] 的每个元素,并将Pre[i + 1][j + 1]的值更新为Pre[i + 1][j] + Pre[i][j] + 1] – Pre[i][j]然后将Pre[i + 1][j + 1]增加1如果arr[i][j]小于或等于mid
    • 初始化一个变量,如果mid的值可能或不作为中位数,则将其标记false以存储。
    • 迭代每个可能的值 [K, N]*[K, N](i, j)然后执行以下步骤:
      • 在左上角顶点为(i – K, j – K)和右下角顶点为(i, j)的方形子矩阵中查找小于或等于mid的元素数,然后将其存储在变量中,例如XPre[i][j] – Pre[i – K][j] – Pre[i][j – K]+ Pre[i – K][j – K]
      • 如果X小于(K 2 +1)/2,则标记标志为真并跳出循环。
    • 如果标志真,则将low的值更新为(mid + 1) 。否则,将high的值更新为mid
  • 完成上述步骤后,将low的值打印为在所有可能的大小为K*K的方形子矩阵中得到的最大中值。

下面是上述方法的实现:

C++
// C++ program for the above approach
 
#include 
using namespace std;
 
// Function to determine if a given
// value can be median
bool isMaximumMedian(vector >& arr,
                     int N, int K, int mid)
{
    // Stores the prefix sum array
    vector > Pre(
        N + 5, vector(N + 5, 0));
 
    // Traverse the matrix arr[][]
    for (int i = 0; i < N; ++i) {
        for (int j = 0; j < N; ++j) {
 
            // Update Pre[i+1][j+1]
            Pre[i + 1][j + 1] = Pre[i + 1][j]
                                + Pre[i][j + 1]
                                - Pre[i][j];
 
            // If arr[i][j] is less
            // than or equal to mid
            if (arr[i][j] <= mid)
                Pre[i + 1][j + 1]++;
        }
    }
 
    // Stores the count of elements
    // should be less than mid
    int required = (K * K + 1) / 2;
 
    // Stores if the median mid
    // can be possible or not
    bool flag = 0;
 
    // Iterate over the range [K, N]
    for (int i = K; i <= N; ++i) {
 
        // Iterate over the range [K, N]
        for (int j = K; j <= N; ++j) {
 
            // Stores count of elements less
            // than or equal to the value
            // mid in submatrix with bottom
            // right vertices at (i, j)
            int X = Pre[i][j] - Pre[i - K][j]
                    - Pre[i][j - K]
                    + Pre[i - K][j - K];
 
            // If X is less than or
            // equal to required
            if (X < required)
                flag = 1;
        }
    }
 
    // Return flag
    return flag;
}
 
// Function to find the maximum median
// of a subsquare of the given size
int maximumMedian(vector >& arr,
                  int N, int K)
{
    // Stores the range of the
    // search space
    int low = 0, high = 1e9;
 
    // Iterate until low is less
    // than high
    while (low < high) {
 
        // Stores the mid value of
        // the range [low, high]
        int mid = low + (high - low) / 2;
 
        // If the current median can
        // be possible
        if (isMaximumMedian(arr, N, K, mid)) {
 
            // Update the value of low
            low = mid + 1;
        }
        else {
 
            // Update the value of high
            high = mid;
        }
    }
 
    // Return value stored in low as
    // answer
    return low;
}
 
// Driver Code
int main()
{
    vector > arr
        = { { 1, 5, 12 }, { 6, 7, 11 }, { 8, 9, 10 } };
    int N = arr.size();
    int K = 2;
    cout << maximumMedian(arr, N, K);
 
    return 0;
}


Java
// Java program for the above approach
public class GFG
{
 
// Function to determine if a given
// value can be median
static boolean isMaximumMedian(int arr[][] , int N, int K, int mid)
{
   
    // Stores the prefix sum array
    int [][]Pre = new int [N+5][N+5];
 
    // Traverse the matrix arr[][]
    for (int i = 0; i < N; ++i) {
        for (int j = 0; j < N; ++j) {
 
            // Update Pre[i+1][j+1]
            Pre[i + 1][j + 1] = Pre[i + 1][j]
                                + Pre[i][j + 1]
                                - Pre[i][j];
 
            // If arr[i][j] is less
            // than or equal to mid
            if (arr[i][j] <= mid)
                Pre[i + 1][j + 1]++;
        }
    }
 
    // Stores the count of elements
    // should be less than mid
    int required = (K * K + 1) / 2;
 
    // Stores if the median mid
    // can be possible or not
    boolean flag = false;
 
    // Iterate over the range [K, N]
    for (int i = K; i <= N; ++i) {
 
        // Iterate over the range [K, N]
        for (int j = K; j <= N; ++j) {
 
            // Stores count of elements less
            // than or equal to the value
            // mid in submatrix with bottom
            // right vertices at (i, j)
            int X = Pre[i][j] - Pre[i - K][j]
                    - Pre[i][j - K]
                    + Pre[i - K][j - K];
 
            // If X is less than or
            // equal to required
            if (X < required)
                flag = true;
        }
    }
 
    // Return flag
    return flag;
}
 
// Function to find the maximum median
// of a subsquare of the given size
static int maximumMedian(int arr[][], int N, int K)
{
    // Stores the range of the
    // search space
    int low = 0, high = (int)1e9;
 
    // Iterate until low is less
    // than high
    while (low < high) {
 
        // Stores the mid value of
        // the range [low, high]
        int mid = low + (high - low) / 2;
 
        // If the current median can
        // be possible
        if (isMaximumMedian(arr, N, K, mid)) {
 
            // Update the value of low
            low = mid + 1;
        }
        else {
 
            // Update the value of high
            high = mid;
        }
    }
 
    // Return value stored in low as
    // answer
    return low;
}
 
// Driver Code
public static void main(String args[])
{
   int [][] arr = { { 1, 5, 12 }, { 6, 7, 11 }, { 8, 9, 10 } };
    int N = arr.length;
    int K = 2;
    System.out.print( maximumMedian(arr, N, K));
}
}
 
// This code is contributed by SoumikMondal


Python3
# Python3 program for the above approach
 
# Function to determine if a given
# value can be median
def isMaximumMedian(arr, N, K, mid):
     
    # Stores the prefix sum array
    Pre = [[0 for x in range(N + 5)]
              for y in range(N + 5)]
 
    # Traverse the matrix arr[][]
    for i in range(N):
        for j in range(N):
 
            # Update Pre[i+1][j+1]
            Pre[i + 1][j + 1] = (Pre[i + 1][j] +
                                 Pre[i][j + 1] -
                                 Pre[i][j])
 
            # If arr[i][j] is less
            # than or equal to mid
            if (arr[i][j] <= mid):
                Pre[i + 1][j + 1] += 1
 
    # Stores the count of elements
    # should be less than mid
    required = (K * K + 1) // 2
 
    # Stores if the median mid
    # can be possible or not
    flag = 0
 
    # Iterate over the range [K, N]
    for i in range(K, N + 1):
 
        # Iterate over the range [K, N]
        for j in range(K, N + 1):
 
            # Stores count of elements less
            # than or equal to the value
            # mid in submatrix with bottom
            # right vertices at (i, j)
            X = (Pre[i][j] - Pre[i - K][j] -
                 Pre[i][j - K] + Pre[i - K][j - K])
 
            # If X is less than or
            # equal to required
            if (X < required):
                flag = 1
 
    # Return flag
    return flag
 
# Function to find the maximum median
# of a subsquare of the given size
def maximumMedian(arr, N, K):
     
    # Stores the range of the
    # search space
    low = 0
    high = 1000000009
 
    # Iterate until low is less
    # than high
    while (low < high):
 
        # Stores the mid value of
        # the range [low, high]
        mid = low + (high - low) // 2
 
        # If the current median can
        # be possible
        if (isMaximumMedian(arr, N, K, mid)):
 
            # Update the value of low
            low = mid + 1
 
        else:
 
            # Update the value of high
            high = mid
 
    # Return value stored in low as
    # answer
    return low
 
# Driver Code
if __name__ == "__main__":
 
    arr = [ [ 1, 5, 12 ],
            [ 6, 7, 11 ],
            [ 8, 9, 10 ] ]
    N = len(arr)
    K = 2
     
    print(maximumMedian(arr, N, K))
 
# This code is contributed by ukasp


C#
// C# program for the above approach
using System;
 
class GFG{
 
// Function to determine if a given
// value can be median
static bool isMaximumMedian(int[,] arr, int N,
                            int K, int mid)
{
     
    // Stores the prefix sum array
    int [,]Pre = new int[N + 5, N + 5];
 
    // Traverse the matrix arr[][]
    for(int i = 0; i < N; ++i)
    {
        for(int j = 0; j < N; ++j)
        {
             
            // Update Pre[i+1][j+1]
            Pre[i + 1, j + 1] = Pre[i + 1, j] +
                                Pre[i, j + 1] -
                                Pre[i, j];
 
            // If arr[i][j] is less
            // than or equal to mid
            if (arr[i, j] <= mid)
                Pre[i + 1, j + 1]++;
        }
    }
 
    // Stores the count of elements
    // should be less than mid
    int required = (K * K + 1) / 2;
 
    // Stores if the median mid
    // can be possible or not
    bool flag = false;
 
    // Iterate over the range [K, N]
    for(int i = K; i <= N; ++i)
    {
         
        // Iterate over the range [K, N]
        for(int j = K; j <= N; ++j)
        {
             
            // Stores count of elements less
            // than or equal to the value
            // mid in submatrix with bottom
            // right vertices at (i, j)
            int X = Pre[i, j] - Pre[i - K, j] -
                    Pre[i, j - K] + Pre[i - K, j - K];
 
            // If X is less than or
            // equal to required
            if (X < required)
                flag = true;
        }
    }
 
    // Return flag
    return flag;
}
 
// Function to find the maximum median
// of a subsquare of the given size
static int maximumMedian(int[,] arr, int N, int K)
{
     
    // Stores the range of the
    // search space
    int low = 0, high = (int)1e9;
 
    // Iterate until low is less
    // than high
    while (low < high)
    {
         
        // Stores the mid value of
        // the range [low, high]
        int mid = low + (high - low) / 2;
 
        // If the current median can
        // be possible
        if (isMaximumMedian(arr, N, K, mid))
        {
             
            // Update the value of low
            low = mid + 1;
        }
        else
        {
             
            // Update the value of high
            high = mid;
        }
    }
 
    // Return value stored in low as
    // answer
    return low;
}
 
// Driver code
public static void Main(string[] args)
{
    int [,] arr = { { 1, 5, 12 },
                    { 6, 7, 11 },
                    { 8, 9, 10 } };
    int N = arr.GetLength(0);
    int K = 2;
     
    Console.WriteLine(maximumMedian(arr, N, K));
}
}
 
// This code is contributed by avijitmondal1998


Javascript


输出:
9

时间复杂度: O(N 2 * log(10 9 ))
辅助空间: O(N 2 )

如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程学生竞争性编程现场课程