给定一个由非负整数和整数K组成的大小为N 的方阵arr[][] ,任务是找到大小为K的方阵子矩阵的元素的最大中值。
例子:
Input: arr[][] = {{1, 5, 12}, {6, 7, 11}, {8, 9, 10}}, N = 3, K = 2
Output: 9
Explanation:
The median of all subsquare of size 2*2 are:
- The subsquare {{1, 5}, {6, 7}} has the median equal to 5.
- The subsquare {{5, 12}, {7, 11}} has the median equal to 7.
- The subsquare {{6, 7}, {8, 9}} has the median equal to 7.
- The subsquare {{7, 11}, {9, 10}} has the median equal to 9.
Therefore, the maximum possible median value among all possible square matrix is equal to 9.
Input: arr[][] = {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 10, 11}, {12, 13, 14, 13}}, N = 4, K = 2
Output: 11
朴素方法:解决上述给定问题的最简单方法是迭代每个大小为K*K 的子矩阵,然后在形成的所有子矩阵中找到最大中值。
时间复杂度: O(N 2 * K 2 )
辅助空间: O(1)
高效方法:上述问题可以基于以下观察进行优化:
- 如果M是方形子矩阵的中值,则该子矩阵中小于或等于M的数字的计数必须小于(K 2 +1)/2 。
- 这个想法是使用二分搜索来找到给定的中值:
- 如果大小为K×K 的任何子矩阵中小于M的数字计数小于(K 2 +1)/2,则增加左边界。
- 否则,递减右边界。
- 这个想法是使用矩阵的前缀和来计算方形子矩阵中恒定时间内小于特定值的元素。
请按照以下步骤解决问题:
- 初始化两个变量,低为0 ,高为INT_MAX,表示搜索空间的范围。
- 迭代直到低小于高并执行以下步骤:
- 找到范围[low, high]的中间值并将其存储在一个变量中,比如mid 。
- 初始化向量的向量说Pre以在前缀子矩阵中存储小于或等于mid的元素计数。
- 使用变量i和j迭代矩阵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的元素数,然后将其存储在变量中,例如X为Pre[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 现场工作专业课程和学生竞争性编程现场课程。