Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Index/双指针.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
| [1004. 最大连续1的个数 III](https://leetcode-cn.com/problems/max-consecutive-ones-iii/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/max-consecutive-ones-iii/solution/san-chong-jie-fa-cong-dong-tai-gui-hua-d-gxks/) | 中等 | 🤩🤩🤩 |
| [1052. 爱生气的书店老板](https://leetcode-cn.com/problems/grumpy-bookstore-owner/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/grumpy-bookstore-owner/solution/hua-dong-chuang-kou-luo-ti-by-ac_oier-nunu/) | 中等 | 🤩🤩🤩 |
| [1221. 分割平衡字符串](https://leetcode-cn.com/problems/split-a-string-in-balanced-strings/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/split-a-string-in-balanced-strings/solution/gong-shui-san-xie-noxiang-xin-ke-xue-xi-wumnk/) | 简单 | 🤩🤩🤩🤩 |
| [1332. 删除回文子序列](https://leetcode-cn.com/problems/remove-palindromic-subsequences/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/remove-palindromic-subsequences/solution/gong-shui-san-xie-jian-dan-mo-ni-ti-by-a-0zwn/) | 中等 | 🤩🤩🤩🤩 |
| [1332. 删除回文子序列](https://leetcode-cn.com/problems/remove-palindromic-subsequences/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/remove-palindromic-subsequences/solution/gong-shui-san-xie-jian-dan-mo-ni-ti-by-a-0zwn/) | 简单 | 🤩🤩🤩🤩 |
| [1446. 连续字符](https://leetcode-cn.com/problems/consecutive-characters/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/consecutive-characters/solution/gong-shui-san-xie-jian-dan-shuang-zhi-zh-xtv6/) | 简单 | 🤩🤩🤩🤩🤩 |
| [1610. 可见点的最大数目](https://leetcode-cn.com/problems/maximum-number-of-visible-points/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/maximum-number-of-visible-points/solution/gong-shui-san-xie-qiu-ji-jiao-ji-he-ti-b-0bid/) | 困难 | 🤩🤩🤩🤩 |
| [1743. 从相邻元素对还原数组](https://leetcode-cn.com/problems/restore-the-array-from-adjacent-pairs/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/restore-the-array-from-adjacent-pairs/solution/gong-shui-san-xie-yi-ti-shuang-jie-dan-x-elpx/) | 中等 | 🤩🤩🤩🤩 |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ Tag : 「二分」、「前缀和」



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

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


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

示例 1:
![](https://assets.leetcode.com/uploads/2021/03/18/sum-grid.jpg)

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

Expand All @@ -28,11 +28,11 @@ Tag : 「二分」、「前缀和」
```

提示:
* m == matrix.length
* n == matrix[i].length
* 1 <= m, n <= 100
* -100 <= matrix[i][j] <= 100
* -$10^5$ <= k <= $10^5$
* $m == matrix.length$
* $n == matrix[i].length$
* $1 <= m, n <= 100$
* $-100 <= matrix[i][j] <= 100$
* -$10^5 <= k <= 10^5$

---

Expand All @@ -46,8 +46,8 @@ Tag : 「二分」、「前缀和」

数据范围是 $10^2$,对应的计算量是 $10^8$,理论上会超时,但当我们枚举「矩形左上角」$(i,j)$ 的时候,我们只需要搜索位于 $(i,j)$ 的右下方的点 $(p,q)$ 作为「矩形右下角」,所以其实我们是取不满 $m^2 * n^2$ 的,但仍然具有超时风险(2021/04/20 Java 测试可通过,C++ 使用 `vector` 会 TLE)。

代码:
```Java []
Java 代码:
```Java
class Solution {
public int maxSumSubmatrix(int[][] mat, int k) {
int m = mat.length, n = mat[0].length;
Expand All @@ -74,6 +74,35 @@ class Solution {
}
}
```
C++ 代码:
```C++
int sum[110][110];
class Solution {
public:
int maxSumSubmatrix(vector<vector<int>>& mat, int k) {
int m = mat.size(), n = mat[0].size();
for(int i = 1; i <= m; i++){
for(int j = 1; j <= n; j++){
sum[i][j] = sum[i - 1][j] + sum[i][j - 1] - sum[i - 1][j - 1] + mat[i - 1][j - 1];
}
}
int ans = INT_MIN;
for(int i = 1; i <= m; i++){
for(int j = 1; j <= n; j++){
for(int p = i; p <= m; p++){
for(int q = j; q <= n; q++){
int cur = sum[p][q] - sum[i - 1][q] - sum[p][j - 1] + sum[i - 1][j - 1];
if(cur <= k){
ans = max(ans,cur);
}
}
}
}
}
return ans;
}
};
```
* 时间复杂度:预处理前缀和数组复杂度为 $O(m * n)$,查找答案的复杂度为 $O(m^2 * n^2)$。整体复杂度为 $O(m^2 * n^2)$。
* 空间复杂度:$O(m * n)$

Expand Down Expand Up @@ -149,8 +178,8 @@ $$

至此,我们通过预处理前缀和 + 容斥原理彻底将题目转化为「一维问题」进行来求解。

代码:
```Java []
Java 代码:
```Java
class Solution {
public int maxSumSubmatrix(int[][] mat, int k) {
int m = mat.length, n = mat[0].length;
Expand Down Expand Up @@ -190,6 +219,38 @@ class Solution {
}
}
```
C++ 代码:
```C++
class Solution {
public:
int maxSumSubmatrix(vector<vector<int>>& mat, int k) {
int m = mat.size(), n = mat[0].size();
vector<vector<int>> sum(m + 1,vector<int>(n + 1,0));
for(int i = 1; i <= m; i++){
for(int j = 1; j <= n; j++){
sum[i][j] = sum[i - 1][j] + sum[i][j - 1] - sum[i - 1][j - 1] + mat[i - 1][j - 1];
}
}
int ans = INT_MIN;
for(int top = 1; top <= m; top++){
for(int bot = top; bot <= m; bot++){
set<int> st;
st.insert(0);
for(int r = 1; r <= n; r++){
int right = sum[bot][r] - sum[top - 1][r];
auto left = st.lower_bound(right - k);
if(left != st.end()){
int cur = right - *left;
ans = max(ans,cur);
}
st.insert(right);
}
}
}
return ans;
}
};
```
* 时间复杂度:枚举上下边界复杂度为 $O(m^2)$;枚举右边界为 $O(n)$,使用 `TreeSet`(基于红黑树)存储和查找左边界复杂度为 $O(\log{n})$。整体复杂度为 $O(m^2 * n\log{n})$
* 空间复杂度:$O(m * n)$

Expand All @@ -201,8 +262,8 @@ class Solution {

事实上,我们需要将「二分过程」应用到数值较大的行或者列之中,这样才能最大化我们查找的效率(同时也回答了本题的进阶部分)。

代码:
```Java []
Java 代码:
```Java
class Solution {
public int maxSumSubmatrix(int[][] mat, int k) {
int m = mat.length, n = mat[0].length;
Expand Down Expand Up @@ -234,6 +295,39 @@ class Solution {
}
}
```
C++ 代码:
```C++
class Solution {
public:
int maxSumSubmatrix(vector<vector<int>>& mat, int k) {
int m = mat.size(), n = mat[0].size();
vector<vector<int>> sum(m + 1,vector<int>(n + 1,0));
for(int i = 1; i <= m; i++){
for(int j = 1; j <= n; j++){
sum[i][j] = sum[i - 1][j] + sum[i][j - 1] - sum[i - 1][j - 1] + mat[i - 1][j - 1];
}
}
bool isRight = n > m;
int ans = INT_MIN;
for(int i = 1; i <= (isRight ? m : n); i++){
for(int j = i; j <= (isRight ? m : n); j++){
set<int> st;
st.insert(0);
for(int fixed = 1; fixed <= (isRight ? n : m); fixed++){
int a = isRight ? sum[j][fixed] - sum[i - 1][fixed] : sum[fixed][j] - sum[fixed][i - 1];
auto b = st.lower_bound(a - k);
if(b != st.end()){
int cur = a - *b;
ans = max(ans,cur);
}
st.insert(a);
}
}
}
return ans;
}
};
```
* 时间复杂度:预处理「每行」或「每列」的前缀和,复杂度为 $O(m * n)$;枚举子矩阵的「上下行」或「左右行」,复杂度为 $O(\min(m, n)^2)$;结合二维前缀和套用一维最大连续子数组解决方案,复杂度为$\max(m, n)\log{\max(m, n)}$。整体复杂度为 $O(\min(m, n)^2 * \max(m, n)\log{\max(m, n)})$
* 空间复杂度:$O(m * n)$

Expand All @@ -245,8 +339,8 @@ class Solution {

因此我们可以将计算前缀和的逻辑下放到搜索子矩阵的循环里去做,从而将 $O(m * n)$ 的空间复杂度下降到 $O(\max(m,n))$。

代码:
```Java []
Java 代码:
```Java
class Solution {
public int maxSumSubmatrix(int[][] mat, int k) {
int m = mat.length, n = mat[0].length;
Expand Down Expand Up @@ -275,18 +369,49 @@ class Solution {
}
}
```
C++ 代码:
```C++
class Solution {
public:
int maxSumSubmatrix(vector<vector<int>>& mat, int k) {
int m = mat.size(), n = mat[0].size();
bool isRight = n > m;
vector<int> sum((isRight ? n + 1 : m + 1), 0);
int ans = INT_MIN;
for(int i = 1; i <= (isRight ? m : n); i++){
fill(sum.begin(),sum.end(),0);
for(int j = i; j <= (isRight ? m : n); j++){
set<int> st;
st.insert(0);
int a = 0;
for(int fixed = 1; fixed <= (isRight ? n : m); fixed++){
sum[fixed] += isRight ? mat[j - 1][fixed - 1] : mat[fixed - 1][j - 1];
a += sum[fixed];
auto b = st.lower_bound(a - k);
if(b != st.end()){
int cur = a - *b;
ans = max(ans,cur);
}
st.insert(a);
}
}
}
return ans;
}
};
```
* 时间复杂度:预处理「每行」或「每列」的前缀和,复杂度为 $O(m * n)$;枚举子矩阵的「上下行」或「左右行」,复杂度为 $O(\min(m, n)^2)$;结合二维前缀和套用一维最大连续子数组解决方案,复杂度为$\max(m, n)\log{max(m, n)}$。整体复杂度为 $O(\min(m, n)^2 * \max(m, n)\log{\max(m, n)})$
* 空间复杂度:$O(\max(m, n))$

---

### 最后

这是我们「刷穿 LeetCode」系列文章的第 `No.363` 篇,系列开始于 2021/01/01,截止于起始日 LeetCode 上共有 1916 道题目,部分是有锁题,我们将先将所有不带锁的题目刷完
这是我们「刷穿 LeetCode」系列文章的第 `No.363` 篇,系列开始于 2021/01/01,截止于起始日 LeetCode 上共有 1916 道题目,部分是有锁题,我们将先把所有不带锁的题目刷完

在这个系列文章里面,除了讲解解题思路以外,还会尽可能给出最为简洁的代码。如果涉及通解还会相应的代码模板。

为了方便各位同学能够电脑上进行调试和提交代码,我建立了相关的仓库:https://github.com/SharingSource/LogicStack-LeetCode。
为了方便各位同学能够电脑上进行调试和提交代码,我建立了相关的仓库:https://github.com/SharingSource/LogicStack-LeetCode

在仓库地址里,你可以看到系列文章的题解链接、系列文章的相应代码、LeetCode 原题链接和其他优选题解。

4 changes: 2 additions & 2 deletions LeetCode/611-620/611. 有效三角形的个数(中等).md
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ Tag : 「排序」、「二分」、「双指针」
2,2,3
```
注意:
1. 数组长度不超过1000
2. 数组里整数的范围为 [0, 1000]。
1. 数组长度不超过 $1000$
2. 数组里整数的范围为 $[0, 1000]$

---

Expand Down