leetcode1030

leetcode1030_距离顺序排列矩阵单元格

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

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

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

实例:
输入: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]]。

暴力排序

这个题目很简单,就是表里二维坐标上的每个点,然后进行排序,很容易就想到了广度优先遍历,但我们这里先把最暴力的写法写出来,只需要把每个点保存到数组中,然后排序即可。

public int[][] allCellsDistOrder(int R, int C, int r0, int c0) {
    /**
         * 值得学习的一种二维数组的初始化方式!!! 实际上想要初始化一个二维数组不一定非要值得这个二维数组的shape
         * 只需要知道最外层的大小即可! 里面可以继续重新new.
         * 这里我们知道[0,0]到[R,C]一共有 R*C个点,只需要求出每个点对应的坐标并放入二维数组即可。
         * 所以有[i*C + j]表示第个点的坐标,
         * 然后sort
         * 即
         */
    int[][] ret = new int[R * C][];  // 可以这样初始化?

    for (int i = 0; i < R; i++) {
        for (int j = 0; j < C; j++) {
            ret[i * C + j] = new int[]{i, j};
        }
    }
    Arrays.sort(ret, new Comparator<int[]>() {
        @Override
        public int compare(int[] a, int[] b) {
            return (Math.abs(a[0] - r0) + Math.abs(a[1] - c0)) - (Math.abs(b[0] - r0) + Math.abs(b[1] - c0));
        }
    });
    return ret;
}

桶排序

上面这个方法是时间复杂度是O(R·Clog(R·C))。也就是快排的速度。但实际上这个排序的范围是有限的,也就是[0,0] ->[R,C]。实际在枚举所有点时,我们可以直接按照哈曼顿距离分桶。这样我们就可以实现线性的桶排序。

接下来就是复习桶排序:

桶排序利用函数的映射关系,减少了几乎所有的比较工作。实际上,桶排序的f(k)值的计算,其作用就相当于快排中划分,已经把大量数据分割成了基本有序的数据块(桶)。然后只需要对桶中的少量数据做先进的比较排序即可。

    public int[][] allCellsDistOrder(int R, int C, int r0, int c0) {
        // 找到桶的上界
        int maxDist = Math.max(r0, R - 1 - r0) + Math.max(c0, C - 1 - c0);
        List<List<int[]>> bucket = new ArrayList<List<int[]>>();
        for (int i = 0; i <= maxDist; i++) {
            bucket.add(new ArrayList<int[]>());
        }

        for (int i = 0; i < R; i++) {
            for (int j = 0; j < C; j++) {
                int d = dist(i, j, r0, c0);
                bucket.get(d).add(new int[]{i, j});
            }
        }
        int[][] ret = new int[R * C][];
        int index = 0;
        for (int i = 0; i <= maxDist; i++) {
            for (int[] it : bucket.get(i)) {
                ret[index++] = it;
            }
        }
        return ret;
    }

    public int dist(int r1, int c1, int r2, int c2) {
        return Math.abs(r1 - r2) + Math.abs(c1 - c2);
    }

广度优先遍历

复习stream

posted @ 2023-01-19 19:25  SsoZh  阅读(12)  评论(0编辑  收藏  举报