53. 最大子序和
给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。这一题大家应该都做过,基本思路是从左到右求数组和tmpSum += arr[i],一旦和tmpSum<0, 就重置tmpSum=0. 遍历一遍就能求最大和,具体证明略。
那么进入正题, 最大子矩阵是求一个矩阵中的和最大的子矩阵
原题如下:
给定一个正整数、负整数和 0 组成的 N × M 矩阵,编写代码找出元素总和最大的子矩阵。
返回一个数组 [r1, c1, r2, c2],其中 r1, c1 分别代表子矩阵左上角的行号和列号,r2, c2 分别代表右下角的行号和列号。若有多个满足条件的子矩阵,返回任意一个均可。
示例:
输入:
[
[-1,0],
[0,-1]
]
输出:[0,1,0,1]
解释:输入中标粗的元素即为输出所表示的矩阵
解法:
这里的核心变化就是以前的一维数组变成了二维数组,题目难度直接easy转hard哈哈。
那一维数组的解法很简单,二维数组是不是有办法搞成一维数组再求解呢?
没错,我们拿两个下标i, j 分别表示第i行到第j行, 并把他们压缩到一行,套用一维数组的方式求解
这里我们需要定义个中间变量tmpArr []int, 在里面存上i-j行内每一列的数字和,之后遍历tmpArr即可求解。
看到这里豁然开朗了么?
上代码:
func getMaxMatrix(matrix [][]int) []int {
// 这题的核心是二维矩阵转一维数组,也就是把i-j层的数据压缩到一层一维数组中计算
if len(matrix) == 0 {
return nil
}
var b []int // 中间变量,用来压缩二维数组
var max = math.MinInt64
var maxRes []int // 结果数组
for i := range matrix {
b = make([]int, len(matrix[i]))
for j := i; j < len(matrix); j++ {
// 这里把每一层的数据都加和到b中,模拟一维数组
var tmp,kSIdx int // 数字和,该行数字的起始下标
for k, n := range matrix[j] {
// 先把第j行的数据加和到b中
b[k] += n
// 一维数组求连续最大和问题
tmp += b[k]
if tmp > max {
max = tmp
maxRes = []int{i, kSIdx, j, k}
}
// 如果s->k和小于0,则重置tmp, 并把起始下标推到下一位
if tmp < 0 {
tmp = 0
kSIdx = k+1
}
}
}
}
return maxRes
}