https://leetcode-cn.com/problems/matrix-cells-in-distance-order/
给出 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
输出:[[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:
输入:R = 2, C = 3, r0 = 1, c0 = 2
输出:[[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
小菜鸡的尝试:
尝试是失败了,但也有思考。按曼哈顿距离输出点。那要么暴力地全部求一遍曼哈顿距离,最后排序。或是有一种数据结构可以把距离和点对应起来然后类似优先队列那样可以自动排序。虽然思想是一样的,但应该后面那一种耗时少一点点。
膜拜大佬代码:
Version1:
这就是我之前讲的思路,于我而言学到了一个数据结构multimap
1 class Solution { 2 public: 3 vector<vector<int>> allCellsDistOrder(int R, int C, int r0, int c0) { 4 int distance = 0; 5 multimap<int, vector<int>> map;//因为存在距离相同的情况,所以用multimap 6 vector<vector<int>> output; 7 //遍历元矩阵,依次求各个单元格到指定单元格的曼哈顿距离,将坐标和距离插入multmap 8 for(int i=0; i<R; i++){ 9 for(int j=0; j<C; j++){ 10 distance = abs(i-r0) + abs(j-c0); 11 vector<int> temp; 12 temp.push_back(i); 13 temp.push_back(j); 14 map.insert(pair<int, vector<int>>(distance, temp)); 15 } 16 } 17 multimap<int, vector<int>>::iterator i; 18 //遍历multmap输出答案 19 for(i=map.begin();i!=map.end();i++){ 20 output.push_back((*i).second); 21 } 22 return output; 23 } 24 };
Version2:
1 public: 2 vector<vector<int>> allCellsDistOrder(int R, int C, int r0, int c0) { 3 vector<vector<int>> res; 4 for(int dis=0; dis< R+C-1; dis++) 5 { 6 for(int dr=0; dr<=dis; dr++) 7 { 8 int dc = dis - dr; 9 if(dr>=1 && dc>=1 && r0-dr>=0 && c0-dc>=0) 10 { 11 res.push_back(vector<int>{r0-dr, c0-dc}); 12 } 13 if(dr>=1 && dc>=0 && r0-dr>=0 && c0+dc<C) 14 { 15 res.push_back(vector<int>{r0-dr, c0+dc}); 16 } 17 if(dr>=0 && dc>=1 && r0+dr<R && c0-dc>=0) 18 { 19 res.push_back(vector<int>{r0+dr, c0-dc}); 20 } 21 if(dr>=0 && dc>=0 && r0+dr<R && c0+dc<C) 22 { 23 res.push_back(vector<int>{r0+dr, c0+dc}); 24 } 25 } 26 } 27 return res; 28 } 29 };
这个解答看了很久才看懂,通俗来讲,这跳出了我们按照先对每一个点计算距离再排序的思维。因为曼哈顿距离就是水平距离+垂直距离,因此我们很容易得到距离的最小值和最大值,那么只需要遍历距离集合,按照四个象限的特征计算出符合条件的点加入即可。
Version3:
这是一个非常明确的广度优先,思维上和Version2有点相似,都是现有距离再有点。Version2用总距离控制是否出边界,这里用 nx<0||nx>=R||ny<0||ny>=C 这个判断条件判断是否出边界。因为广度优先所以可能会计算相同的点,为了避免重复操作,判断vis[][]的值是否为1即可得知该点是否已经经过计算。
1 const int maxn = 1005; 2 class Solution { 3 public: 4 int dx[4]={1,-1,0,0}; 5 int dy[4]={0,0,1,-1}; 6 int vis[maxn][maxn]; 7 vector<vector<int>> bfs(int R,int C,int r0,int c0){ 8 queue<pair<int,int> >Q; 9 vector<vector<int>> res; 10 Q.push({r0,c0}); 11 vis[r0][c0]=1; 12 while(!Q.empty()){ 13 pair<int,int> now = Q.front(); 14 Q.pop(); 15 res.push_back({now.first,now.second}); 16 for(int i=0;i<4;i++){ 17 int nx = now.first+dx[i]; 18 int ny = now.second+dy[i]; 19 if(nx<0||nx>=R||ny<0||ny>=C) 20 continue; 21 if(vis[nx][ny])continue; 22 vis[nx][ny]=1; 23 Q.push({nx,ny}); 24 } 25 } 26 return res; 27 } 28 vector<vector<int>> allCellsDistOrder(int R, int C, int r0, int c0) { 29 vector<vector<int>> res = bfs(R,C,r0,c0); 30 return res; 31 } 32 };
今天三个题解看下来!受益匪浅!!冲冲冲!!