返回

JavaScript如何掌握LeetCode 1029.距离顺序排列矩阵单元格

前端





## 前言

欢迎来到LeetCode系列文章的新一篇章,今天我们将一起探索「1029. 距离顺序排列矩阵单元格」这道题。这道题不仅考验算法设计能力,更需要我们对数据结构和优化技巧的娴熟掌握。通过本文,我们将从头到尾带你领略JavaScript解决该题的风采,并逐步掌握BFS与哈希法的妙用。

## 题意

给你一个下标从 0 开始的二维整数数组 matrix ,其中 matrix[r][c] 是第 r 行和第 c 列的元素。

同时给你一个数组 r0 和 c0 ,其中 r0 是 matrix 的行下标,c0 是 matrix 的列下标。

返回 matrix 的所有元素按照与 (r0, c0) 的距离升序排列后的结果。

换言之,按与 (r0, c0) 的 曼哈顿距离 从最小的到最大的顺序返回 matrix 的所有元素。

**示例 1:** 

输入:matrix = [[1,0,1],[0,1,0],[1,0,1]], r0 = 1, c0 = 1
输出:[[0,1,0],[1,0,1],[1,0,1]]
解释:

  • (1, 1) 到 (1, 1) 的距离为 0。
  • (0, 0) 到 (1, 1) 的距离为 1。
  • (2, 0) 到 (1, 1) 的距离为 1。
  • (2, 2) 到 (1, 1) 的距离为 2。
  • (0, 2) 到 (1, 1) 的距离为 2。
    按距离从小到大排列后得到 [[0,1,0],[1,0,1],[1,0,1]]。

**示例 2:** 

输入:matrix = [[1,0,0],[0,0,0],[0,0,0]], r0 = 1, c0 = 2
输出:[[1,0,0],[0,0,0],[0,0,0]]
解释:

  • (1, 2) 到 (1, 2) 的距离为 0。
  • (0, 0) 到 (1, 2) 的距离为 2。
  • (0, 1) 到 (1, 2) 的距离为 2。
  • (0, 2) 到 (1, 2) 的距离为 2。
  • (2, 0) 到 (1, 2) 的距离为 2。
  • (2, 1) 到 (1, 2) 的距离为 2。
  • (2, 2) 到 (1, 2) 的距离为 2。
    按距离从小到大排列后得到 [[1,0,0],[0,0,0],[0,0,0]]。

## 解法1:BFS+哈希

### 分析

距离顺序排列矩阵单元格,其实质就是找到矩阵中每个元素与给定单元格的曼哈顿距离,并根据距离进行排序。为此,我们可以采用广度优先搜索(BFS)和哈希表联手出击,先求出每个单元格到给定单元格的距离,再利用哈希表记录距离与单元格的对应关系,最后按照距离从小到大对单元格进行排序。

1. **BFS求距离:** 

首先,我们利用BFS算法求出矩阵中每个单元格到给定单元格的曼哈顿距离。BFS的流程如下:

- 将给定单元格(r0, c0)加入队列。
- 循环执行以下操作,直到队列为空:
  - 从队列中取出当前单元格。
  - 将当前单元格的上下左右四个相邻单元格加入队列(注意越界)。
  - 记录当前单元格到给定单元格的距离。

2. **哈希表存距离:** 

接下来,我们使用哈希表来记录距离与单元格的对应关系。具体做法是:

- 对于矩阵中的每个单元格,计算其到给定单元格的距离。
- 将距离作为哈希表的键,单元格本身作为哈希表的值。

3. **排序输出结果:** 

最后,我们将哈希表中的键值对按照距离从小到大进行排序,并将排序后的单元格输出。

### 代码实现

```javascript
/**
 * 1029. 距离顺序排列矩阵单元格
 * 给你一个下标从 0 开始的二维整数数组 matrix,其中 matrix[r][c] 是第 r 行和第 c 列的元素。
 * 同时给你一个数组 r0 和 c0,其中 r0 是 matrix 的行下标,c0 是 matrix 的列下标。
 * 返回 matrix 的所有元素按照与 (r0, c0) 的距离升序排列后的结果。
 * 换言之,按与 (r0, c0) 的 曼哈顿距离 从最小的到最大的顺序返回 matrix 的所有元素。
 * 示例 1:
 * 输入:matrix = [[1,0,1],[0,1,0],[1,0,1]], r0 = 1, c0 = 1
 * 输出:[[0,1,0],[1,0,1],[1,0,1]]
 * 示例 2:
 * 输入:matrix = [[1,0,0],[0,0,0],[0,0,0]], r0 = 1, c0 = 2
 * 输出:[[1,0,0],[0,0,0],[0,0,0]]
 * 提示:
 * m == matrix.length
 * n == matrix[r].length
 * 1 <= m, n <= 100
 * 0 <= r0 < m
 * 0 <= c0 < n
 * 1 <= matrix[r][c] <= 100
 */
const allCellsDistOrder = (matrix, r0, c0) => {
  // BFS求距离
  const distance = bfs(matrix, r0, c0);

  // 哈希表存距离
  const hash = {};
  for (let i = 0; i < matrix.length; i++) {
    for (let j = 0; j < matrix[0].length; j++) {
      hash[distance[i][j]] = hash[distance[i][j]] || [];
      hash[distance[i][j]].push([i, j]);
    }
  }

  // 排序输出结果
  const result = [];
  for (const key in hash) {
    result.push(...hash[key]);
  }
  return result;
};

// BFS求距离
const bfs = (matrix, r0, c0) => {
  const m = matrix.length;
  const n = matrix[0].length;
  const distance = Array.from({ length: m }, () => Array(n).fill(0));
  const queue = [[r0, c0]];
  while (queue.length) {
    const [r, c] = queue.shift();
    if (r < 0 || r >= m || c < 0 || c >= n || matrix[r][c] === 0) {
      continue;
    }
    distance[r][c] = distance[r0][c0] + 1;
    matrix[r][c] = 0;  // 标记已访问
    queue.push([r - 1, c], [r + 1, c], [r, c - 1], [r, c + 1]);
  }
  return distance;
};

复杂度分析

  • 时间复杂度: BFS的时间复杂度为O(mn),哈希表的插入和查找都是O(1),因此总的时间复杂度为O(mn)。
  • 空间复杂度: BFS的空间复杂度为O(mn),哈希表的空间复杂度为O(mn),因此总的空间复杂度为O(mn)。

结语

通过本文,我们一起深入剖析了LeetCode 1029题的解法,并一步步实现了解决方案。从BFS的巧妙运用到哈希表的灵活搭配,希望你对算法设计