|
@@ -0,0 +1,91 @@
|
|
|
+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
|
|
|
+ }
|
|
|
+}
|
|
|
+
|