# 距离顺序排列矩阵单元格(1030)
# 题目
给出 R 行 C 列的矩阵,其中的单元格的整数坐标为 (r, c),满足 0 <= r < R 且 0 <= c < C。
另外,我们在该矩阵中给出了一个坐标为 (r0, c0) 的单元格。
返回矩阵中的所有单元格的坐标,并按到 (r0, c0) 的距离从最小到最大的顺序排,其中,两单元格(r1, c1) 和 (r2, c2) 之间的距离是曼哈顿距离,|r1 - r2| + |c1 - c2|。(你可以按任何满足此条件的顺序返回答案。)
# 示例
输入:R = 1
, C = 2
, r0 = 0
, c0 = 0
输出:[[0,0],[0,1]]
输入:R = 2
, C = 2
, r0 = 0
, c0 = 1
输出:[[0,1],[0,0],[1,1],[1,0]]
输入:R = 2
, C = 3
, r0 = 1
,c0 = 2
输出:[[1,2],[0,2],[1,1],[0,1],[1,0],[0,0]]
# 提示
- 1 <= R <= 100
- 1 <= C <= 100
- 0 <= r0 < R
- 0 <= c0 < C
# 算法
# 使用sort排序
先将矩阵中所有点遍历出来,然后排序
export const allCellsDistOrder = (R, C, r0, c0) => {
const points = [];
for (let r = 0; r < R; r++) {
for (let c = 0; c < C; c++) {
points.push([r, c]);
}
}
points.sort((a, b) => {
const distanceA = Math.abs(a[0] - r0) + Math.abs(a[1] - c0);
const distanceB = Math.abs(b[0] - r0) + Math.abs(b[1] - c0);
return distanceA - distanceB;
});
return points;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
# 桶排序
每个桶中放入距离相同的点,桶的下标(数组中每一项)为桶中点的距离,然后合并这些桶(因为满足距离相同即可,所以桶中不必排序)
export const allCellsDistOrder = (R, C, r0, c0) => {
const disArr = [];
for (let r = 0; r < R; r++) {
for (let c = 0; c < C; c++) {
const distance = Math.abs(r0 - r) + Math.abs(c0 - c);
disArr[disArr] ? disArr[distance].push([r, c]) : (disArr[distance] = [[r, c]]);
}
}
const res = [];
disArr.forEach((item) => {
res.push(...item);
});
return res;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
# BFS
曼哈顿距离阵列
如下图:
5 4 3 2 3 4 5
4 3 2 1 2 3 4
3 2 1 0 1 2 3
4 3 2 1 2 3 4
5 4 3 2 3 4 5
1
2
3
4
5
2
3
4
5
可以看到距离较给定点(r0,c0)
扩散向外增大,即我们不需要求距离并比较,从点(r0,c0)
依次向外查找点推入结果数组,且过滤掉已经推入结果的点,最后就能得到结果
- 创建一个和位置阵列相同行列数的矩阵
visited
,用来存储某个位置的点是否已经被放入结果数组,防止重复取点。初始全部填充false
,将目标点位置visited[r0][c0]
设置为true
- 初始化一个队列
queue
用来存放遍历到的相邻的有效的点,默认填充目标点[r0,c0]
- 每次取出队列
queue
中的第一个点,推入结果数组res
,然后以这个点为中心判断上下左右四个方向的点是否在范围内、是否不在queue
或res
中,如果都满足则推入队列queue
作为之后待判断的中心点;这样队列queue
可以保证每次从队列头取出的元素都是距离依次递增的(因为推入queue
尾的时候就是按照上下左右的顺序从内向外推入的) - 直到队列
queue
为空时,跳出循环,返回结果res
export const allCellsDistOrder = (R, C, r0, c0) => {
const visited = new Array(R).fill(0).map(() => new Array(C).fill(false));
visited[r0][c0] = true;
const queue = [[r0, c0]];
const res = [];
while (queue.length) {
const point = queue.shift();
res.push(point);
const x = point[0],
y = point[1];
visited[x][y] = true;
if (y - 1 >= 0 && !visited[x][y - 1]) {
queue.push([x, y - 1]);
visited[x][y - 1] = true;
}
if (y + 1 < C && !visited[x][y + 1]) {
queue.push([x, y + 1]);
visited[x][y + 1] = true;
}
if (x - 1 >= 0 && !visited[x - 1][y]) {
queue.push([x - 1, y]);
visited[x - 1][y] = true;
}
if (x + 1 < R && !visited[x + 1][y]) {
queue.push([x + 1, y]);
visited[x + 1][y] = true;
}
}
return res;
};
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
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