共两道题,都是不难,还是记录一下:
1、在一个一维数组中,找出连续子数组的最大和:LeetCode - 53. Maximum Subarray
2、在一个二维矩阵中,找出子矩阵最大和:https://www.51nod.com/Challenge/Problem.html#problemId=1051
一、数组子数组最大和
Given an integer array nums, find the contiguous subarray (containing at least one number) which has the largest sum and return its sum.
Input: [-2,1,-3,4,-1,2,1,-5,4], Output: 6
Explanation: [4,-1,2,1] has the largest sum = 6.
Follow up:
If you have figured out the O(n) solution, try coding another solution using the divide and conquer approach, which is more subtle.
就是连续的子数组中,找出和最大的。首先最容易想到的就是 O ( N ) O(N) O(N) 的 solution,用一个 cur 值记录之前总和,当总和加当前值 < 当前位置值时,cur 就变成当前位置值,否则就累加。
int maxSubArray(vector<int>& nums) {
int max_sum = INT_MIN, cur_sum = 0;
for (const int& i : nums) {
cur_sum = max(i, cur_sum + i);
max_sum = max(max_sum, cur_sum);
}
return max_sum;
}
二、二维矩阵子矩阵最大和
一个 M*N 的矩阵,找到此矩阵的一个子矩阵,并且这个子矩阵的元素的和是最大的,输出这个最大的值。
例如:3*3 的矩阵:
-1 3 -1
2 -1 3
-3 1 2
和最大的子矩阵是(和为 7):
3 -1
-1 3
1 2
其实,和上边的题一样的,不过就是多了一(维,上边的题,其实是用一个 dp 数组,存储以每个位置结尾的子数组最大和,这道题就是用一个 pre_sum 数组,存储每一列为结尾的子矩阵最大和。
原题输入是先是列,然后是行,坑死。。
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int maxSum(vector<vector<int>> &arr) {
if (arr.empty()) return 0;
const int M = arr.size(), N = arr[0].size();
int max_sum = INT_MIN;
for (int i = 0; i < M; i++) {
vector<int> pre_sum(N, 0); // 每一列的presum
for (int j = i; j < M; j++) { // [i, j]行
int cur = 0;
for (int k = 0; k < N; k++) {
pre_sum[k] += arr[j][k];
cur += pre_sum[k];
max_sum = max(max_sum, cur);
cur = cur < 0 ? 0 : cur;
}
//for (const int& p : pre_sum)
// cout << p << " ";
//cout << endl;
}
}
return max_sum;
}
int main() {
int m, n;
cin >> n >> m;
vector<vector<int>> mat(m, vector<int>(n));
for (int i = 0; i < m; i++)
for (int j = 0; j < n; j++)
cin >> mat[i][j];
cout << maxSum(mat) << endl;
}
pre_sum 结果
-1 3 -1
1 2 2
-2 3 4
2 -1 3
-1 0 5
-3 1 2
看懂 pre_sum 的输出,就看懂了,其实 pre_sum 的计算有很多重复的部分,不过AC了就记录个思想就好。