363.max-sum-of-rectangle-no-larger-than-k.go 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. func maxSumSubmatrix(matrix [][]int, k int) (max int) {
  2. m := len(matrix)
  3. if m == 0 {
  4. return 0
  5. }
  6. n := len(matrix[0])
  7. if n == 0 {
  8. return 0
  9. }
  10. // Remember how to calculate the maximum sum of rectangles in a matrix:
  11. //
  12. // l, r dp l r dp l, r dp
  13. // -1 -4 0 -1 . -4 . -5 . . . .
  14. // 3 -3 4 3 --\ . -3 . 0 --\ ... --\ . . . .
  15. // 4 8 7 4 --/ . 8 . 12 --/ --/ . . . .
  16. // 6 20 1 6 . 20 . 26 . . . .
  17. //
  18. // Then, calculate the maximum sum of ranges in 1D array (dp).
  19. // Given the target k, the problem is : find the largest sum closest to k in dp.
  20. // Time compexity: O(n^2mlog(m)), n < m.
  21. max = -1 << 32
  22. if m < n { // Ensure n <= m
  23. m, n = n, m
  24. matrix = transpose(matrix)
  25. }
  26. for l := 0; l < n; l++ {
  27. dp := make([]int, m) // m rows
  28. for r := l; r < n; r++ {
  29. sum := []int{0}
  30. currSum := 0
  31. for i := 0; i < m; i++ {
  32. dp[i] += matrix[i][r]
  33. currSum += dp[i]
  34. idx := lower_bound(sum, currSum-k)
  35. if idx != len(sum) {
  36. max = maxInt(max, currSum-sum[idx])
  37. }
  38. insert(&sum, currSum)
  39. }
  40. }
  41. }
  42. return
  43. }
  44. func maxInt(x, y int) int {
  45. if x < y {
  46. return y
  47. }
  48. return x
  49. }
  50. func transpose(matrix [][]int) [][]int {
  51. m, n := len(matrix), len(matrix[0])
  52. res := make([][]int, n)
  53. for i := 0; i < n; i++ {
  54. res[i] = make([]int, m)
  55. for j := 0; j < m; j++ {
  56. res[i][j] = matrix[j][i]
  57. }
  58. }
  59. return res
  60. }
  61. func lower_bound(nums []int, val int) int {
  62. beg, end := 0, len(nums)-1
  63. for beg <= end {
  64. mid := beg + (end-beg)/2
  65. if nums[mid] < val {
  66. beg = mid + 1
  67. } else if val < nums[mid] {
  68. end = mid - 1
  69. } else {
  70. return mid
  71. }
  72. }
  73. return beg
  74. }
  75. func insert(nums *[]int, val int) { // nums is a set.
  76. i := lower_bound(*nums, val)
  77. if n := len(*nums); i == n {
  78. *nums = append(*nums, val)
  79. } else if (*nums)[i] != val {
  80. newNums := make([]int, n+1)
  81. copy(newNums, (*nums)[:i])
  82. newNums[i] = val
  83. copy(newNums[i+1:], (*nums)[i:])
  84. *nums = newNums
  85. }
  86. }