12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091 |
- func maxSumSubmatrix(matrix [][]int, k int) (max int) {
- m := len(matrix)
- if m == 0 {
- return 0
- }
- n := len(matrix[0])
- if n == 0 {
- return 0
- }
- // Remember how to calculate the maximum sum of rectangles in a matrix:
- //
- // l, r dp l r dp l, r dp
- // -1 -4 0 -1 . -4 . -5 . . . .
- // 3 -3 4 3 --\ . -3 . 0 --\ ... --\ . . . .
- // 4 8 7 4 --/ . 8 . 12 --/ --/ . . . .
- // 6 20 1 6 . 20 . 26 . . . .
- //
- // Then, calculate the maximum sum of ranges in 1D array (dp).
- // Given the target k, the problem is : find the largest sum closest to k in dp.
- // Time compexity: O(n^2mlog(m)), n < m.
- max = -1 << 32
- if m < n { // Ensure n <= m
- m, n = n, m
- matrix = transpose(matrix)
- }
- for l := 0; l < n; l++ {
- dp := make([]int, m) // m rows
- for r := l; r < n; r++ {
- sum := []int{0}
- currSum := 0
- for i := 0; i < m; i++ {
- dp[i] += matrix[i][r]
- currSum += dp[i]
- idx := lower_bound(sum, currSum-k)
- if idx != len(sum) {
- max = maxInt(max, currSum-sum[idx])
- }
- insert(&sum, currSum)
- }
- }
- }
- return
- }
- func maxInt(x, y int) int {
- if x < y {
- return y
- }
- return x
- }
- func transpose(matrix [][]int) [][]int {
- m, n := len(matrix), len(matrix[0])
- res := make([][]int, n)
- for i := 0; i < n; i++ {
- res[i] = make([]int, m)
- for j := 0; j < m; j++ {
- res[i][j] = matrix[j][i]
- }
- }
- return res
- }
- func lower_bound(nums []int, val int) int {
- beg, end := 0, len(nums)-1
- for beg <= end {
- mid := beg + (end-beg)/2
- if nums[mid] < val {
- beg = mid + 1
- } else if val < nums[mid] {
- end = mid - 1
- } else {
- return mid
- }
- }
- return beg
- }
- func insert(nums *[]int, val int) { // nums is a set.
- i := lower_bound(*nums, val)
- if n := len(*nums); i == n {
- *nums = append(*nums, val)
- } else if (*nums)[i] != val {
- newNums := make([]int, n+1)
- copy(newNums, (*nums)[:i])
- newNums[i] = val
- copy(newNums[i+1:], (*nums)[i:])
- *nums = newNums
- }
- }
|