{x}
blog image

Max Sum of Rectangle No Larger Than K

Given an m x n matrix matrix and an integer k, return the max sum of a rectangle in the matrix such that its sum is no larger than k.

It is guaranteed that there will be a rectangle with a sum no larger than k.

 

Example 1:

Input: matrix = [[1,0,1],[0,-2,3]], k = 2
Output: 2
Explanation: Because the sum of the blue rectangle [[0, 1], [-2, 3]] is 2, and 2 is the max number no larger than k (k = 2).

Example 2:

Input: matrix = [[2,2,-1]], k = 3
Output: 3

 

Constraints:

  • m == matrix.length
  • n == matrix[i].length
  • 1 <= m, n <= 100
  • -100 <= matrix[i][j] <= 100
  • -105 <= k <= 105

 

Follow up: What if the number of rows is much larger than the number of columns?

Solution Explanation: Maximum Sum of Rectangle No Larger Than K

This problem asks to find the maximum sum of a rectangle within a given matrix, with the constraint that this sum must not exceed a given integer k. The solution presented uses a combination of enumeration and an ordered set (like a TreeSet in Java or SortedSet in Python) for efficient searching.

Approach:

  1. Iterate through all possible rectangles: The outer loops iterate through all possible top-left and bottom-right corners (i and j for rows, implicitly defining the rectangle's height, and iterating through all columns). This nested loop structure has a time complexity of O(m³n) where m is the number of rows and n is the number of columns.

  2. Calculate column sums: For each rectangle, the inner loop calculates the sum of elements in each column within the selected rectangle. This sum is accumulated in the nums array. This step has a time complexity of O(n) for each rectangle.

  3. Kadane's Algorithm with Binary Search Enhancement: The core of the algorithm lies in efficiently finding the maximum subarray sum within the nums array that does not exceed k. While a simple Kadane's algorithm could be used, the provided solution leverages an ordered set to optimize this search, reducing the time complexity from O(n²) to O(n log n).

  4. Ordered Set for Efficient Search: The SortedSet (or TreeSet) stores cumulative sums encountered while traversing nums. For each new cumulative sum s, it efficiently finds (using binary search within the set) the smallest cumulative sum p such that s - p is less than or equal to k. This s - p represents a subarray sum. The largest such s - p found is then considered.

Time Complexity Analysis:

  • Outer loops iterating through rectangles: O(m²n)
  • Inner loop calculating column sums: O(n) for each rectangle
  • Ordered set operations (insertion and binary search): O(n log n) for each rectangle

Therefore, the overall time complexity is dominated by the nested loops and the ordered set operations: O(m²n * n log n) = O(m²n² log n). In the best-case scenario (small rectangles), it will be closer to O(m²n log n). However, the worst-case performance will be O(m²n² log n).

Space Complexity Analysis:

The space complexity is dominated by the nums array (size n) and the ordered set (whose size can be at most n in the worst case). Therefore, the space complexity is O(n).

Code Explanation (Python):

The Python code efficiently implements this approach:

import sys
from sortedcontainers import SortedSet
 
class Solution:
    def maxSumSubmatrix(self, matrix: List[List[int]], k: int) -> int:
        m, n = len(matrix), len(matrix[0])
        ans = -sys.maxsize  # Initialize with negative infinity
 
        for i in range(m):
            nums = [0] * n
            for j in range(i, m):
                for h in range(n):
                    nums[h] += matrix[j][h]
 
                s = 0
                ts = SortedSet([0]) # Initialize the sorted set with 0
 
                for x in nums:
                    s += x
                    p = ts.bisect_left(s - k)  # Binary search in the set
 
                    if p != len(ts):
                        ans = max(ans, s - ts[p])  # Update the maximum sum
 
                    ts.add(s)  # Add the cumulative sum to the set
 
        return ans

The other languages (Java, C++, Go, and TypeScript) follow a similar structure, using their respective ordered set implementations (e.g., TreeSet in Java). The core logic of iterating through rectangles, calculating column sums, and using the ordered set for efficient search remains the same.