C++前缀和算法应用:矩形区域不超过 K 的最大数值和

简介: C++前缀和算法应用:矩形区域不超过 K 的最大数值和

基础知识点

C++算法:前缀和、前缀乘积、前缀异或的原理、源码及测试用例

题目

给你一个 m x n 的矩阵 matrix 和一个整数 k ,找出并返回矩阵内部矩形区域的不超过 k 的最大数值和。

题目数据保证总会存在一个数值和不超过 k 的矩形区域。

示例 1:

输入:matrix = [[1,0,1],[0,-2,3]], k = 2

输出:2

解释:蓝色边框圈出来的矩形区域 [[0, 1], [-2, 3]] 的数值和是 2,且 2 是不超过 k 的最大数字(k = 2)。

示例 2:

输入:matrix = [[2,2,-1]], k = 3

输出:3

提示:

m == matrix.length

n == matrix[i].length

1 <= m, n <= 100

-100 <= matrix[i][j] <= 100

-105 <= k <= 105

分析

二维前缀和

vPreSum[r][c] 记录以(0,0)开始,宽高为c r的矩形和。vPreSum[r][c] = vPreSum[r - 1][c] + vPreSum[r][c - 1] + matrix[r - 1][c - 1] - vPreSum[r - 1][c - 1];

vPreSum[r - 1][c] 绿色实心矩形的和
vPreSum[r][c - 1] 蓝色空心矩形
matrix[r - 1][c - 1] 黄色矩形
vPreSum[r - 1][c - 1] 蓝绿重叠部分

时间复杂度O(nnn*logn)

枚举所有矩形,时间复杂度是O(n^4),超时。三层循环,第一层和第二层循环,枚举左右。第三层循环枚举下,setSum记录了所有合法的t的构成的矩形(left,0,right,t-1)的和。显然iLeftRight - setSum任意元素的值,就是(left,t,right,row)矩形的和。iLeftRight 是矩形(left,0,right,row)的和。对setSum 进行二分。

源码

class Solution {
public:
int maxSumSubmatrix(vector<vector>& matrix, int k) {
m_r = matrix.size();
m_c = matrix.front().size();
vector<vector> vPreSum(m_r+1,vector(m_c+1,0)); //vPreSum[r][c] 以(0,0)开始,宽高为c r的矩形
for (int r = 1; r <= m_r; r++)
{
for (int c = 1; c <= m_c; c++)
{
//令r=1,c=1 vPreSum[1][1] = 0 +0 + matrix[0][0] -0
//令r=2,c=2 vPreSum[2][2] = vPreSum[1][2] +vPreSum[2][1] + matrix[1][1] + vPreSum[1][1]
vPreSum[r][c] = vPreSum[r - 1][c] + vPreSum[r][c - 1] + matrix[r - 1][c - 1] - vPreSum[r - 1][c - 1];
}
}
int iMin = INT_MIN;
//vector<vector> vDebug(m_r, vector(m_c,INT_MIN));
for (int left = 0; left < m_c ; left++ )
{
for (int right = left ; right < m_c; right++ )
{
//row和right 是右下角的坐标
set setSum = { 0 };
for (int row = 0; row < m_r; row++)
{
const int iLeftRight = vPreSum[row + 1][right + 1]
• vPreSum[row + 1][left];
//iLeftRight - x <=k ==> -x <= k - iLeftRight ==> x >= iLeftRight-k
auto it = setSum.lower_bound(iLeftRight - k);
if (setSum.end() != it)
{
iMin = max(iMin, iLeftRight - *it);
//vDebug[row][right] = iLeftRight - *it;
}
setSum.emplace(iLeftRight);
}
}
}
return iMin;
}
int m_r, m_c;
};

测试用例

template
void Assert(const vector& v1, const vector& v2)
{
if (v1.size() != v2.size())
{
assert(false);
return;
}
for (int i = 0; i < v1.size(); i++)
{
assert(v1[i] == v2[i]);
}
}
template
void Assert(const T& t1, const T& t2)
{
assert(t1 == t2);
}
int main()
{
vector<vector> matrix = { {1, 2, 3}, { 4,5,6 } };
int k = 2;
auto res = Solution().maxSumSubmatrix(matrix, k);
Assert(res, 2);
matrix = { {1, 0, 1}, { 0,-2,3 } };
k = 2;
res = Solution().maxSumSubmatrix(matrix, k);
Assert(res, 2);
matrix = { {2,2,-1} };
k = 3;
res = Solution().maxSumSubmatrix(matrix, k);
Assert(res, 3);
CConsole::Out(res);
}

扩展阅读

视频课程

有效学习:明确的目标 及时的反馈 拉伸区(难度合适),可以先学简单的课程,请移步CSDN学院,听白银讲师(也就是鄙人)的讲解。

https://edu.csdn.net/course/detail/38771

如何你想快速形成战斗了,为老板分忧,请学习C#入职培训、C++入职培训等课程

https://edu.csdn.net/lecturer/6176

相关下载

想高屋建瓴的学习算法,请下载《闻缺陷则喜算法册》doc版

https://download.csdn.net/download/he_zhidan/88348653

鄙人想对大家说的话
闻缺陷则喜是一个美好的愿望,早发现问题,早修改问题,给老板节约钱。
墨家名称的来源:有所得以墨记之。
如果程序是一条龙,那算法就是他的是睛

测试环境

操作系统:win7 开发环境: VS2019 C++17

或者 操作系统:win10 开发环境: VS2022 C++17


相关文章
|
16天前
|
机器学习/深度学习 安全 算法
【图论】【割点】【C++算法】928. 尽量减少恶意软件的传播 II
【图论】【割点】【C++算法】928. 尽量减少恶意软件的传播 II
|
19天前
|
存储 C++ 容器
C++STL(标准模板库)处理学习应用案例
【4月更文挑战第8天】使用C++ STL,通过`std:vector`存储整数数组 `{5, 3, 1, 4, 2}`,然后利用`std::sort`进行排序,输出排序后序列:`std:vector<int> numbers; numbers = {5, 3, 1, 4, 2}; std:sort(numbers.begin(), numbers.end()); for (int number : numbers) { std::cout << number << " "; }`
19 2
|
30天前
|
安全 算法 C++
【C/C++ 泛型编程 应用篇】C++ 如何通过Type traits处理弱枚举和强枚举
【C/C++ 泛型编程 应用篇】C++ 如何通过Type traits处理弱枚举和强枚举
48 3
|
1天前
|
C++
C++:深度解析与实战应用
C++:深度解析与实战应用
7 1
|
2天前
|
安全 vr&ar C++
C++:编程语言的演变、应用与最佳实践
C++:编程语言的演变、应用与最佳实践
|
8天前
|
算法
代码随想录算法训练营第六十天 | LeetCode 84. 柱状图中最大的矩形
代码随想录算法训练营第六十天 | LeetCode 84. 柱状图中最大的矩形
18 3
|
15天前
|
机器学习/深度学习 算法
【优选算法专栏】专题四:前缀和(二)
【优选算法专栏】专题四:前缀和(二)
21 1
|
17天前
|
算法 测试技术 C#
【广度优先搜索】【堆】【C++算法】407. 接雨水 II
【广度优先搜索】【堆】【C++算法】407. 接雨水 II
|
17天前
|
算法 测试技术 Serverless
【二分查找】【C++算法】378. 有序矩阵中第 K 小的元素
【二分查找】【C++算法】378. 有序矩阵中第 K 小的元素
|
17天前
|
算法 测试技术 C#
【字典树】【KMP】【C++算法】3045统计前后缀下标对 II
【字典树】【KMP】【C++算法】3045统计前后缀下标对 II