跳转至

3567. 子矩阵的最小绝对差

题目描述

给你一个 m x n 的整数矩阵 grid 和一个整数 k

对于矩阵 grid 中的每个连续的 k x k 子矩阵,计算其中任意两个 不同值 之间的 最小绝对差 

返回一个大小为 (m - k + 1) x (n - k + 1) 的二维数组 ans,其中 ans[i][j] 表示以 grid 中坐标 (i, j) 为左上角的子矩阵的最小绝对差。

注意:如果子矩阵中的所有元素都相同,则答案为 0。

子矩阵 (x1, y1, x2, y2) 是一个由选择矩阵中所有满足 x1 <= x <= x2y1 <= y <= y2 的单元格 matrix[x][y] 组成的矩阵。

 

示例 1:

输入: grid = [[1,8],[3,-2]], k = 2

输出: [[2]]

解释:

  • 只有一个可能的 k x k 子矩阵:[[1, 8], [3, -2]]
  • 子矩阵中的不同值为 [1, 8, 3, -2]
  • 子矩阵中的最小绝对差为 |1 - 3| = 2。因此,答案为 [[2]]

示例 2:

输入: grid = [[3,-1]], k = 1

输出: [[0,0]]

解释:

  • 每个 k x k 子矩阵中只有一个不同的元素。
  • 因此,答案为 [[0, 0]]

示例 3:

输入: grid = [[1,-2,3],[2,3,5]], k = 2

输出: [[1,2]]

解释:

  • 有两个可能的 k × k 子矩阵:
    • (0, 0) 为起点的子矩阵:[[1, -2], [2, 3]]
      • 子矩阵中的不同值为 [1, -2, 2, 3]
      • 子矩阵中的最小绝对差为 |1 - 2| = 1
    • (0, 1) 为起点的子矩阵:[[-2, 3], [3, 5]]
      • 子矩阵中的不同值为 [-2, 3, 5]
      • 子矩阵中的最小绝对差为 |3 - 5| = 2
  • 因此,答案为 [[1, 2]]

 

提示:

  • 1 <= m == grid.length <= 30
  • 1 <= n == grid[i].length <= 30
  • -105 <= grid[i][j] <= 105
  • 1 <= k <= min(m, n)

解法

方法一:枚举

我们可以枚举所有可能的 \(k \times k\) 子矩阵的左上角坐标 \((i, j)\),对于每个子矩阵,我们可以提取出其中的所有元素,放入一个列表 \(\textit{nums}\) 中。然后对 \(\textit{nums}\) 进行排序,接着计算相邻的不同元素之间的绝对差,找到最小的绝对差值。最后将结果存储在一个二维数组中。

时间复杂度 \(O((m - k + 1) \times (n - k + 1) \times k^2 \log(k))\),其中 \(m\)\(n\) 分别是矩阵的行数和列数,而 \(k\) 是子矩阵的大小。空间复杂度 \(O(k^2)\),用于存储每个子矩阵的元素。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
class Solution:
    def minAbsDiff(self, grid: List[List[int]], k: int) -> List[List[int]]:
        m, n = len(grid), len(grid[0])
        ans = [[0] * (n - k + 1) for _ in range(m - k + 1)]
        for i in range(m - k + 1):
            for j in range(n - k + 1):
                nums = []
                for x in range(i, i + k):
                    for y in range(j, j + k):
                        nums.append(grid[x][y])
                nums.sort()
                d = min((abs(a - b) for a, b in pairwise(nums) if a != b), default=0)
                ans[i][j] = d
        return ans
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class Solution {
    public int[][] minAbsDiff(int[][] grid, int k) {
        int m = grid.length, n = grid[0].length;
        int[][] ans = new int[m - k + 1][n - k + 1];
        for (int i = 0; i <= m - k; i++) {
            for (int j = 0; j <= n - k; j++) {
                List<Integer> nums = new ArrayList<>();
                for (int x = i; x < i + k; x++) {
                    for (int y = j; y < j + k; y++) {
                        nums.add(grid[x][y]);
                    }
                }
                Collections.sort(nums);
                int d = Integer.MAX_VALUE;
                for (int t = 1; t < nums.size(); t++) {
                    int a = nums.get(t - 1);
                    int b = nums.get(t);
                    if (a != b) {
                        d = Math.min(d, Math.abs(a - b));
                    }
                }
                ans[i][j] = (d == Integer.MAX_VALUE) ? 0 : d;
            }
        }
        return ans;
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class Solution {
public:
    vector<vector<int>> minAbsDiff(vector<vector<int>>& grid, int k) {
        int m = grid.size(), n = grid[0].size();
        vector<vector<int>> ans(m - k + 1, vector<int>(n - k + 1, 0));
        for (int i = 0; i <= m - k; ++i) {
            for (int j = 0; j <= n - k; ++j) {
                vector<int> nums;
                for (int x = i; x < i + k; ++x) {
                    for (int y = j; y < j + k; ++y) {
                        nums.push_back(grid[x][y]);
                    }
                }
                sort(nums.begin(), nums.end());
                int d = INT_MAX;
                for (int t = 1; t < nums.size(); ++t) {
                    if (nums[t] != nums[t - 1]) {
                        d = min(d, abs(nums[t] - nums[t - 1]));
                    }
                }
                ans[i][j] = (d == INT_MAX) ? 0 : d;
            }
        }
        return ans;
    }
};
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
func minAbsDiff(grid [][]int, k int) [][]int {
    m, n := len(grid), len(grid[0])
    ans := make([][]int, m-k+1)
    for i := range ans {
        ans[i] = make([]int, n-k+1)
    }
    for i := 0; i <= m-k; i++ {
        for j := 0; j <= n-k; j++ {
            var nums []int
            for x := i; x < i+k; x++ {
                for y := j; y < j+k; y++ {
                    nums = append(nums, grid[x][y])
                }
            }
            sort.Ints(nums)
            d := math.MaxInt
            for t := 1; t < len(nums); t++ {
                if nums[t] != nums[t-1] {
                    diff := abs(nums[t] - nums[t-1])
                    if diff < d {
                        d = diff
                    }
                }
            }
            if d != math.MaxInt {
                ans[i][j] = d
            }
        }
    }
    return ans
}

func abs(x int) int {
    if x < 0 {
        return -x
    }
    return x
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
function minAbsDiff(grid: number[][], k: number): number[][] {
    const m = grid.length;
    const n = grid[0].length;
    const ans: number[][] = Array.from({ length: m - k + 1 }, () => Array(n - k + 1).fill(0));
    for (let i = 0; i <= m - k; i++) {
        for (let j = 0; j <= n - k; j++) {
            const nums: number[] = [];
            for (let x = i; x < i + k; x++) {
                for (let y = j; y < j + k; y++) {
                    nums.push(grid[x][y]);
                }
            }
            nums.sort((a, b) => a - b);
            let d = Number.MAX_SAFE_INTEGER;
            for (let t = 1; t < nums.length; t++) {
                if (nums[t] !== nums[t - 1]) {
                    d = Math.min(d, Math.abs(nums[t] - nums[t - 1]));
                }
            }
            ans[i][j] = d === Number.MAX_SAFE_INTEGER ? 0 : d;
        }
    }
    return ans;
}

评论