leetcode
leetcode 1801 ~ 1850
获取单值网格的最小操作数

获取单值网格的最小操作数

难度:

标签:

题目描述

给你一个大小为 m x n 的二维整数网格 grid 和一个整数 x 。每一次操作,你可以对 grid 中的任一元素 x x

单值网格 是全部元素都相等的网格。

返回使网格化为单值网格所需的 最小 操作数。如果不能,返回 -1

 

示例 1:

输入:grid = [[2,4],[6,8]], x = 2
输出:4
解释:可以执行下述操作使所有元素都等于 4 : 
- 2 加 x 一次。
- 6 减 x 一次。
- 8 减 x 两次。
共计 4 次操作。

示例 2:

输入:grid = [[1,5],[2,3]], x = 1
输出:5
解释:可以使所有元素都等于 3 。

示例 3:

输入:grid = [[1,2],[3,4]], x = 2
输出:-1
解释:无法使所有元素相等。

 

提示:

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

代码结果

运行时间: 164 ms, 内存: 37.1 MB


/*
 * 思路:
 * 首先将所有元素转化为一个一维数组,然后检查是否可以通过加减x得到单值网格。
 * 如果每个元素对x的取余数不同,则返回-1。
 * 否则,找到中位数,计算使所有元素变成中位数的操作数。
 */

import java.util.Arrays;
import java.util.stream.IntStream;

public class Solution {
    public int minOperations(int[][] grid, int x) {
        int m = grid.length;
        int n = grid[0].length;
        int[] arr = Arrays.stream(grid).flatMapToInt(Arrays::stream).toArray();
        Arrays.sort(arr);
        int median = arr[arr.length / 2];
        int operations = IntStream.of(arr).map(num -> {
            int diff = Math.abs(num - median);
            if (diff % x != 0) {
                return -1;
            }
            return diff / x;
        }).sum();
        return operations < 0 ? -1 : operations;
    }
}

解释

方法:

此题解采用中位数为目标值的贪心策略。首先,创建一个字典统计每个元素出现的次数。通过遍历网格,将元素及其出现次数存入字典。然后将字典的内容转换为列表,并按元素值排序。通过遍历排序后的列表,寻找中位数作为目标值,因为中位数最小化了加减操作的总数。之后,对每个元素,计算其与目标值的差值。如果差值不是x的倍数,则返回-1,因为这表明无法通过加减x使所有元素值相等。如果差值是x的倍数,计算将该元素调整到目标值需要的操作数,并累加到总操作数中。

时间复杂度:

O(m*n + k*log(k))

空间复杂度:

O(k)

代码细节讲解

🦆
为什么选择中位数作为目标值而不是平均值或其他数值?
中位数作为目标值的选择是由于其在数值分布中的位置能够最小化到每个点的距离总和。在需要通过增加或减少固定数值(此处为 x)来统一所有数值的情况下,中位数能够有效地减少总的操作次数。而平均值虽然在一些统计问题中是好的选择,但在需要以整数操作进行调整的问题中,可能不是整数,也可能不是可通过x的整数倍调整达到的值。
🦆
如果差值不是x的倍数就返回-1,这种情况下是否有可能存在其他数值作为目标值从而使所有元素值通过加减x操作相等?
如果存在任意两个元素之间的差值不是 x 的整数倍,那么无法通过加减操作使这两个元素相等。因此,如果任何一个元素与目标值之间的差不是 x 的倍数,将所有元素调整为相同值的尝试必然失败。这意味着不可能存在其他的数值作为目标值以满足条件。
🦆
在计算操作次数时,为什么将差值除以x后再乘以元素出现的次数,这样的计算逻辑是如何确保正确性的?
将差值除以 x 是为了计算将单个元素调整到目标值需要的基本操作数(即每次操作改变的是 x 单位)。然后乘以该元素出现的次数,是因为每一个相同的元素都需要相同数量的操作来达到目标值。这样的计算逻辑确保了总操作次数反映了使所有元素达到目标值所需的全部操作。
🦆
如何处理网格中所有元素已经相等的情况?在当前的算法实现中,这种情况下的返回值是什么?
如果网格中所有元素已经相等,那么它们本身就已经是目标值,不需要任何操作。在这种情况下,算法中计算差值的部分结果为零,因此总操作数也是零。所以,如果输入的网格中所有元素一开始就相等,算法会返回 0。

相关问题