这是我参与更文挑战的第21天,活动详情查看: 更文挑战
1030. 距离顺序排列矩阵单元格
题目描述
给出 R 行 C 列的矩阵,其中的单元格的整数坐标为 (r, c),满足 0 <= r < R 且 0 <= c < C。
另外,我们在该矩阵中给出了一个坐标为 (r0, c0) 的单元格。
返回矩阵中的所有单元格的坐标,并按到 (r0, c0) 的距离从最小到最大的顺序排,其中,两单元格(r1, c1) 和 (r2, c2) 之间的距离是曼哈顿距离,|r1 - r2| + |c1 - c2|。(你可以按任何满足此条件的顺序返回答案。)
示例 1 :
输入:R = 1, C = 2, r0 = 0, c0 = 0
输入:R = 1, C = 2, r0 = 0, c0 = 0
输出:[[0,0],[0,1]]
解释:从 (r0, c0) 到其他单元格的距离为:[0,1]
示例 2 :
输入:R = 2, C = 2, r0 = 0, c0 = 1
输出:[[0,1],[0,0],[1,1],[1,0]]
解释:从 (r0, c0) 到其他单元格的距离为:[0,1,1,2]
[[0,1],[1,1],[0,0],[1,0]] 也会被视作正确答案。
示例 3:
输出:[[1,2],[0,2],[1,1],[0,1],[1,0],[0,0]]
解释:从 (r0, c0) 到其他单元格的距离为:[0,1,1,2,2,3]
其他满足题目要求的答案也会被视为正确,例如 [[1,2],[1,1],[0,2],[1,0],[0,1],[0,0]]。
提示:
- 1 <= R <= 100
- 1 <= C <= 100
- 0 <= r0 < R
- 0 <= c0 < C
友情链接
思路解析
此题我们用桶排序算法来解。
- 初始化桶。先根据曼哈顿距离来确定需要多少个桶。桶的个数也就是矩阵中曼哈顿距离的最大值。
- 从矩阵的原点开始依次遍历各坐标,算出该点坐标与给定坐标点的曼哈顿距离。并将该点坐标放入对应的桶里。
- 根据桶的结构,所有坐标点已经排好序。封装成返回参数的格式进行输出。
算法实现
class Solution {
public int[][] allCellsDistOrder(int rows, int cols, int rCenter, int cCenter) {
int maxDist = Math.max(rCenter, rows-1-rCenter)+Math.max(cCenter,cols-1-cCenter);
List<List<int[]>> bucket=new ArrayList<List<int[]>>();
for(int i=0;i<=maxDist;i++){
bucket.add(i,new ArrayList<int[]>());
}
for(int i=0;i<rows;i++){
for(int j=0;j<cols;j++){
int dist=dist(i,j,rCenter,cCenter);
bucket.get(dist).add(new int[]{i,j});
}
}
int ret[][]=new int[rows*cols][];
int index=0;
for(int i=0;i<=maxDist;i++){
for(int[] bt:bucket.get(i)){
ret[index++]=bt;
}
}
return ret;
}
public int dist(int r1,int r2,int c1,int c2){
return Math.abs(r1-c1)+Math.abs(r2-c2);
}
}
运行结果
另类写法
另外这种解法巧妙利用了 TreeMap 的数据结构,但是效率不是很好。比较看看就行。
class Solution {
public int[][] allCellsDistOrder(int R, int C, int r0, int c0) {
var distMap = new TreeMap<Integer,List<int[]>>();
for (int i = 0; i < R; i++) {
for (int j = 0; j < C; j++) {
int dist = Math.abs(r0 - i) + Math.abs(c0 - j);
distMap.computeIfAbsent(dist, k -> new ArrayList<int[]>()).add(new int[] {i,j});
}
}
return distMap.values().stream().flatMap(List::stream).toArray(int[][]::new);
}
}