{x}
blog image

Minimum Operations to Make a Uni-Value Grid

You are given a 2D integer grid of size m x n and an integer x. In one operation, you can add x to or subtract x from any element in the grid.

A uni-value grid is a grid where all the elements of it are equal.

Return the minimum number of operations to make the grid uni-value. If it is not possible, return -1.

 

Example 1:

Input: grid = [[2,4],[6,8]], x = 2
Output: 4
Explanation: We can make every element equal to 4 by doing the following: 
- Add x to 2 once.
- Subtract x from 6 once.
- Subtract x from 8 twice.
A total of 4 operations were used.

Example 2:

Input: grid = [[1,5],[2,3]], x = 1
Output: 5
Explanation: We can make every element equal to 3.

Example 3:

Input: grid = [[1,2],[3,4]], x = 2
Output: -1
Explanation: It is impossible to make every element equal.

 

Constraints:

  • m == grid.length
  • n == grid[i].length
  • 1 <= m, n <= 105
  • 1 <= m * n <= 105
  • 1 <= x, grid[i][j] <= 104

Solution Explanation: Minimum Operations to Make a Uni-Value Grid

This problem asks for the minimum number of operations needed to make all elements in a grid equal. The allowed operation is adding or subtracting a fixed value x to any element.

Core Idea:

The solution leverages the observation that if a uni-value grid is achievable, all elements must have the same remainder when divided by x. This is because adding or subtracting x doesn't change the remainder. The approach consists of these steps:

  1. Remainder Check: First, verify if all elements in the grid have the same remainder when divided by x. If not, making a uni-value grid is impossible, and we return -1.

  2. Median Selection: If the remainder check passes, we flatten the grid into a 1D array (nums). Sorting this array allows us to efficiently find the median. The median is chosen as the target value because it minimizes the total number of operations required to make all elements equal to that value.

  3. Operation Count: Finally, we iterate through the sorted array, calculating the absolute difference between each element and the median, dividing by x (to get the number of operations for that element), and summing these up to get the total minimum operations.

Time and Space Complexity:

  • Time Complexity: O((m * n) * log(m * n)). The dominant factor is sorting the flattened array of size m * n.
  • Space Complexity: O(m * n). We need space to store the flattened array.

Code Implementation (Python):

class Solution:
    def minOperations(self, grid: List[List[int]], x: int) -> int:
        nums = []
        first_remainder = grid[0][0] % x  # Get the remainder of the first element
 
        #Check if all elements have the same remainder.
        for row in grid:
            for val in row:
                if val % x != first_remainder:
                    return -1  # Impossible to make uni-value
                nums.append(val)
        
        nums.sort()  #Sort for median calculation
        median = nums[len(nums) // 2]  #Find the median
        operations = 0
 
        #Calculate total operations
        for val in nums:
            operations += abs(val - median) // x
 
        return operations

Code Implementation (Java):

import java.util.Arrays;
 
class Solution {
    public int minOperations(int[][] grid, int x) {
        int[] nums = new int[grid.length * grid[0].length];
        int k = 0;
        int first_remainder = grid[0][0] % x;
 
        //Remainder check
        for (int[] row : grid) {
            for (int val : row) {
                if (val % x != first_remainder) {
                    return -1;
                }
                nums[k++] = val;
            }
        }
        
        Arrays.sort(nums);  //Sort for median
        int median = nums[nums.length / 2];  //Find the median
        int operations = 0;
 
        //Calculate total operations
        for (int val : nums) {
            operations += Math.abs(val - median) / x;
        }
        return operations;
    }
}

The Java and other language implementations follow a similar structure, adapting the syntax and data structures to the respective language. The core logic of remainder checking, sorting, median finding, and operation counting remains consistent across all implementations.