共兩道題,都是不難,還是記錄一下:
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.
就是連續的子數組中,找出和最大的。首先最容易想到的就是 的 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了就記錄個思想就好。