| 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
 
- 	}
 
- }
 
 
  |