距离顺序排列矩阵单元格

给出 R 行 C 列的矩阵,其中的单元格的整数坐标为 (r, c),满足 0 <= r < R 且 0 <= c < C。

另外,我们在该矩阵中给出了一个坐标为 (r0, c0) 的单元格。

返回矩阵中的所有单元格的坐标,并按到 (r0, c0) 的距离从最小到最大的顺序排,其中,两单元格(r1, c1) 和 (r2, c2) 之间的距离是曼哈顿距离,|r1 - r2| + |c1 - c2|。(你可以按任何满足此条件的顺序返回答案。)

 

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/matrix-cells-in-distance-order
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

我认为自己写的这个更容易明白其中的道理,性能上应该差不多,所以就自己可贴出来分享一下,也可以先看这一部分代码,然后再去看官方的答案,有助于理解

  
    public static int[][] allCellsDistOrder4(int R, int C, int r0, int c0) {
        
        int[][] ret = new int[R * C][];
        int index = 0;
        //添加第一个元素
        ret[index++] = new int[]{r0, c0};
        //确认一个最远距离,有多远就需要生成多少个正方形
        int maxDistance = Math.max(r0, R - 1 - r0) + Math.max(c0, C - 1 - c0);
        for (int distance = 1; distance <= maxDistance; distance++) {
            //由{row,c0}作为起点,正方形的四个顶点落在由row=r0,col = c0 组成的轴上
            int moveRow = r0 - distance;
            int moveCol = c0;
            //一共四条边
            //第一条边,右上
            while (true) {
                if (moveRow >= 0 && moveRow < R && moveCol >= 0 && moveCol < C) {
                    ret[index++] = new int[]{moveRow, moveCol};
                }
                moveRow = moveRow + 1;
                moveCol = moveCol + 1;
                if (moveRow == r0) {
                    break;
                }
            }
            //第二条边,左上
            while (true) {
                if (moveRow >= 0 && moveRow < R && moveCol >= 0 && moveCol < C) {
                    ret[index++] = new int[]{moveRow, moveCol};
                }
                moveRow = moveRow + 1;
                moveCol = moveCol - 1;
                if (moveCol == c0) {
                    break;
                }
            }
            //第三条边,左下
            while (true) {
                if (moveRow >= 0 && moveRow < R && moveCol >= 0 && moveCol < C) {
                    ret[index++] = new int[]{moveRow, moveCol};
                }
                moveRow = moveRow - 1;
                moveCol = moveCol - 1;
                if (moveRow == r0) {
                    break;
                }
            }
            //第四条边,右下
            while (true) {
                if (moveRow >= 0 && moveRow < R && moveCol >= 0 && moveCol < C) {
                    ret[index++] = new int[]{moveRow, moveCol};
                }
                moveRow = moveRow - 1;
                moveCol = moveCol + 1;
                if (moveCol == c0) {
                    break;
                }
            }
            
        }
        
        return ret;
    }
  

这个是力扣给的答案,看了半天才明白在说什么:

    
    public static int[][] allCellsDistOrder3(int R, int C, int r0, int c0) {
        
        int[] dr = {1, 1, -1, -1};
        int[] dc = {1, -1, -1, 1};
        //到四个顶点的最大距离
        int maxDist = Math.max(r0, R - 1 - r0) + Math.max(c0, C - 1 - c0);
        int[][] ret = new int[R * C][];
        //起始点座标
        int row = r0, col = c0;
        int index = 0;
        //添加起始点
        ret[index++] = new int[]{row, col};
        for (int dist = 1; dist <= maxDist; dist++) {
            //行减一
            row--;
            //取得四个点,每一次循环完毕,还会回到起始点,方便row再一次减减
            for (int i = 0; i < 4; i++) {
                //i确定一条边,直到遇到下一个端点时停止(数组与i共同确定了边的走向)
                //如果i是2的整数倍,且跟原点不在同一行
                //如果i不是2的整数倍,且跟原点不在同一列
                while ((i % 2 == 0 && row != r0) || (i % 2 != 0 && col != c0)) {
                    //如果行大于0,且行小于最大值,且列大于0,且列小于最大值
                    if (row >= 0 && row < R && col >= 0 && col < C) {
                        //返回值赋值为当前结点
                        ret[index++] = new int[]{row, col};
                    }
                    //在这条边上,运动方向是同向的(只朝一个方向)
                    row += dr[i];
                    col += dc[i];
                }
            }
        }
        return ret;
    }
    
    

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值