leetcode这道题还挺有意思,有的用了桶排序

在这里插入图片描述
第一个想到的就是一层层遍历

class Solution {
     public int[][] allCellsDistOrder(int R, int C, int r0, int c0) {
        int[][] result=new int[R*C][2];
        int index=0;

        boolean[][] visited=new boolean[R][C];//是否访问

        Queue<int[]> queue=new LinkedList<int[]>();  //存储每一层
        queue.offer(new int[]{r0,c0}); //加入根节点
        visited[r0][c0]=true;

        while(!queue.isEmpty()){ //层次遍历
            int[] root=queue.poll();
            result[index++]=root;
            int i=root[0] ,j=root[1];
            if(isLegal(R,C,i-1,j) && !visited[i-1][j]){ //上
                queue.offer(new int[]{i-1,j});  //加入访问过的节点
                visited[i-1][j]=true;
            }
            if(isLegal(R,C,i+1,j) && !visited[i+1][j]){//下
                queue.offer(new int[]{i+1,j});
                visited[i+1][j]=true;
            }
            if(isLegal(R,C,i,j-1) && !visited[i][j-1]){//左
                queue.offer(new int[]{i,j-1});
                visited[i][j-1]=true;
            }
            if(isLegal(R,C,i,j+1) && !visited[i][j+1]){//右
                queue.offer(new int[]{i,j+1});
                visited[i][j+1]=true;
            }
        }
        return result;
    }

    private boolean isLegal(int R, int C ,int i, int j){ //检查下标是否合法
        return i>=0 && i<R && j>=0 && j<C;
    }
}


在这里插入图片描述
不去记录是否访问,提前规定好定义域


class Solution {
     public int[][] allCellsDistOrder(int R, int C, int r0, int c0) {
        int[][] result=new int[R*C][2];
        int index=0;

        Queue<int[]> queue=new LinkedList<int[]>();
        queue.offer(new int[]{r0,c0}); //加入根节点
        
        while(!queue.isEmpty()){ //层次遍历
            int[] root=queue.poll();
            result[index++]=root;
            int i=root[0] ,j=root[1];
            //提前规定好边界
            if(i<=r0 && i-1>=0) queue.offer(new int[]{i-1,j});
            if(i>=r0 && i+1<R)  queue.offer(new int[]{i+1,j});
            if(i==r0 && j<=c0 && j-1>=0 ) queue.offer(new int[]{i,j-1});
            if(i==r0 && j>=c0 && j+1<C) queue.offer(new int[]{i,j+1});      
        }
        return result;
    }
}

在这里插入图片描述
时间短了很多

桶排序
遍历所有坐标,按照距离的大小分组,每组的距离相等(即放入一个桶中)
按照距离从小到大的原则,遍历所有桶,并输出结果
本解法关键在于求得可能的最大距离,即行距离和列距离都最大时:max(r0, R - 1 - r0) + max(c0, C - 1 - c0)


import java.util.ArrayList;
import java.util.LinkedList;

class Solution {
    public int[][] allCellsDistOrder(int R, int C, int r0, int c0) {
        int[][] re = new int[R * C][2];
        int maxDist = Math.max(r0, R - 1 - r0) + Math.max(c0, C - 1 - c0);
        ArrayList<LinkedList<Pos>> bucket = new ArrayList<>(maxDist + 1);
        for (int i = 0; i <= maxDist; i++) {
            bucket.add(new LinkedList<>());
        }

        for (int i = 0; i < R; i++) {
            for (int j = 0; j < C; j++) {
                int d = dist(i, j, r0, c0);
                LinkedList<Pos> list = bucket.get(d);
                list.add(new Pos(i,j));
            }
        }
        int cnt = 0;
        for (int i = 0; i <= maxDist; i++) {
            LinkedList<Pos> list = bucket.get(i);
            if (list.isEmpty()) continue;
            for (Pos p : list) {
                re[cnt][0] = p.r;
                re[cnt][1] = p.c;
                cnt++;
            }
        }

        return re;
    }

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

    private static class Pos {
        int r;
        int c;

        public Pos(int r, int c) {
            this.r = r;
            this.c = c;
        }
    }
}


在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值