Before attempting this problem, you should be comfortable with:
Greedy Algorithms - Making locally optimal choices to achieve a global optimum
Sorting - Ordering elements to prioritize selection of the best candidates
Modular Arithmetic - Understanding how positions repeat in tiled patterns using modulo operations
2D Matrix Manipulation - Working with row and column indices in a grid
1. Greedy
Intuition
The key observation is that the matrix can be viewed as a tiling of sideLength x sideLength squares. Each position within this square pattern repeats throughout the entire matrix. If we place a 1 at position (r, c) within the pattern, it appears at all positions that map to (r, c) when tiled across the matrix.
To maximize the total number of ones, we should place our maxOnes ones at the positions within the pattern that appear most frequently in the full matrix. Positions near the top-left corner of the pattern tile more times because the matrix dimensions may not divide evenly by sideLength.
For each position (r, c) in the pattern, we calculate how many times it appears in the full matrix. Then we greedily pick the maxOnes positions with the highest counts.
Algorithm
For each position (r, c) in the sideLength x sideLength pattern:
Calculate how many times this position appears horizontally: (1 + (width - c - 1) / sideLength).
Calculate how many times it appears vertically: (1 + (height - r - 1) / sideLength).
Multiply these to get the total count for this position.
Collect all counts into a list.
Sort the counts in descending order.
Sum the top maxOnes counts to get the maximum number of ones possible.
classSolution:defmaximumNumberOfOnes(self, width:int, height:int, sideLength:int, maxOnes:int)->int:
count =[]for r inrange(sideLength):for c inrange(sideLength):
num =(1+(width - c -1)// sideLength)*(1+(height - r -1)// sideLength)
count.append(num)
count.sort(reverse=True)returnsum(count[:maxOnes])
classSolution{publicintmaximumNumberOfOnes(int width,int height,int sideLength,int maxOnes){List<Integer> count =newArrayList<>();for(int r =0; r < sideLength;++r){for(int c =0; c < sideLength;++c){
count.add((1+(width -1- c)/ sideLength)*(1+(height -1- r)/ sideLength));}}
count.sort(Comparator.reverseOrder());int answer =0;for(int i =0; i < maxOnes;++i){
answer += count.get(i);}return answer;}}
classSolution{public:intmaximumNumberOfOnes(int width,int height,int sideLength,int maxOnes){
vector<int> count;for(int r =0; r < sideLength;++r){for(int c =0; c < sideLength;++c){
count.push_back((1+(width -1- c)/ sideLength)*(1+(height -1- r)/ sideLength));}}sort(count.begin(), count.end(),greater<int>());int answer =0;for(int i =0; i < maxOnes;++i){
answer += count[i];}return answer;}};
classSolution{/**
* @param {number} width
* @param {number} height
* @param {number} sideLength
* @param {number} maxOnes
* @return {number}
*/maximumNumberOfOnes(width, height, sideLength, maxOnes){const count =[];for(let r =0; r < sideLength;++r){for(let c =0; c < sideLength;++c){
count.push((1+ Math.floor((width -1- c)/ sideLength))*(1+ Math.floor((height -1- r)/ sideLength)));}}
count.sort((a, b)=> b - a);let answer =0;for(let i =0; i < maxOnes;++i){
answer += count[i];}return answer;}}
publicclassSolution{publicintMaximumNumberOfOnes(int width,int height,int sideLength,int maxOnes){List<int> count =newList<int>();for(int r =0; r < sideLength;++r){for(int c =0; c < sideLength;++c){
count.Add((1+(width -1- c)/ sideLength)*(1+(height -1- r)/ sideLength));}}
count.Sort((a, b)=> b.CompareTo(a));int answer =0;for(int i =0; i < maxOnes;++i){
answer += count[i];}return answer;}}
funcmaximumNumberOfOnes(width int, height int, sideLength int, maxOnes int)int{
count :=[]int{}for r :=0; r < sideLength; r++{for c :=0; c < sideLength; c++{
count =append(count,(1+(width-1-c)/sideLength)*(1+(height-1-r)/sideLength))}}
sort.Sort(sort.Reverse(sort.IntSlice(count)))
answer :=0for i :=0; i < maxOnes; i++{
answer += count[i]}return answer
}
class Solution {funmaximumNumberOfOnes(width: Int, height: Int, sideLength: Int, maxOnes: Int): Int {val count = mutableListOf<Int>()for(r in0 until sideLength){for(c in0 until sideLength){
count.add((1+(width -1- c)/ sideLength)*(1+(height -1- r)/ sideLength))}}
count.sortDescending()var answer =0for(i in0 until maxOnes){
answer += count[i]}return answer
}}
Instead of computing and sorting all positions, we can directly calculate the answer by analyzing the structure of the tiled matrix. The matrix divides into regions based on how the sideLength pattern tiles:
Full tiles that appear (height / sideLength) * (width / sideLength) times.
Partial tiles along the right edge, bottom edge, and bottom-right corner.
Positions in the corner remainder region (bottom-right) appear the most frequently because they get counted in the main grid plus both edge strips plus the corner. We should fill these first, then the positions in the edge strips, prioritizing the edge with more repetitions.
Algorithm
Start by placing maxOnes ones in the fully repeated grid sections, contributing maxOnes * (height / sideLength) * (width / sideLength) ones.
Fill positions in the corner remainder region first (size = (height % sideLength) * (width % sideLength)). Each such position contributes to all three remainder regions plus the main grid.
Based on which dimension has more full tiles, fill the appropriate edge strip next.
Fill the remaining edge strip with any leftover positions.
The constraint applies to every sideLength x sideLength submatrix, not just non-overlapping tiles. This means adjacent submatrices overlap, creating a repeating pattern where each position (r, c) in the pattern maps to the same relative position (r % sideLength, c % sideLength) across the entire matrix.
Incorrect Frequency Calculation
When calculating how many times a position in the pattern appears in the full matrix, you must account for partial tiles at the edges. The formula (1 + (width - c - 1) / sideLength) handles this, but off-by-one errors are common. Using (width - c) / sideLength or similar incorrect formulas will give wrong counts.
Swapping Width and Height
The problem distinguishes between width (columns) and height (rows). Confusing these dimensions when calculating horizontal and vertical repetitions leads to incorrect frequency counts, especially when the matrix is not square.
Greedy Selection Order
After computing frequencies, you must select the maxOnes positions with the highest frequencies. Forgetting to sort in descending order or selecting positions with lower frequencies will not maximize the total number of ones in the matrix.