タイトル説明
これで、サイズNの手が十分に0と1とラベル付けされている各「領域」(セル)の上に、Nの「地図」(グリッド)グリッドをxは有します。0が土地を代表して、海、1を表し、あなたは遠いそれが1陸域から海域を知っていますか?最寄りの陸域から海へのエリアをご返送ください。
ここでは、距離"マンハッタン距離"(マンハッタン距離):( X0、Y0の話している ) Y0 | - |と(X1、Y1)は、2つの領域間の距離である| + X0 X1 | y1が- 。
タイトルはleetcodeから来て、入力します
読むのタイトル
例:
1 | 0 | 1 |
---|---|---|
0 | 0 | 0 |
1 | 0 | 1 |
入力:[[1,0,1]、[0,0,0]、[1,0,1]]
出力:2
説明:
海域(1、1)と全ての土地面積の最大値との間の距離2の最大距離。
2なぜそれが結果ですか?数式は、中間セル(1,1)の添加に由来することができ、セルに最も近いセルから他ので(1,1)我々は見つける必要がある点であり、0から1までです。
暴力的な問題解決
ここでは、このものの暴力的な問題解決のコードの最初の期間は、また、正しい答えを得ることができますが、効率が低すぎます。
public static int maxDistance(int[][] grid) {
// 距离陆地区域最远的海洋区域到离它最近的陆地区域的距离
int minDistance = 0;
// 将所有海洋和陆地的坐标分别存储
List<int[]> listLand = new ArrayList<int[]>();
List<int[]> ListOcean = new ArrayList<int[]>();
for (int i = 0; i <grid.length ; i++) {
for (int j = 0; j <grid[i].length ; j++) {
if(grid[i][j]==0){
ListOcean.add(new int[]{i,j});
}else{
listLand.add(new int[]{i,j});
}
}
}
// 如果全部都是海洋或者陆地直接返回-1
if(listLand.size()==0 || ListOcean.size()==0){
return -1;
}
for (int i = 0; i < ListOcean.size(); i++) {
int curMinDistance = 0; // 当前循环海洋区域距离其他陆地区域最近的距离
for (int j = 0; j < listLand.size(); j++) {
// 每个陆地与改海洋点位的距离
int distance = Math.abs(listLand.get(j)[0]-ListOcean.get(i)[0]) + Math.abs(listLand.get(j)[1]-ListOcean.get(i)[1]);
// 如果该海洋距离陆地的点位的距离比其他已比较的点位的最小距离还小 则修改距离陆地的最近距离为该距离
// 首次循环直接赋值
curMinDistance = curMinDistance == 0 ? distance : distance < curMinDistance ? distance : curMinDistance;
}
// 如果该海洋点位与其所有陆地的最小距离比其他海洋点位与所有陆地点位的距离还要小,则认为当前点位为距离陆地区域最远的海洋区域
if(minDistance < curMinDistance){
minDistance = curMinDistance;
}
}
return minDistance;
}
BFSの問題解決
レッツ・すべての陸地面積のポイントを見つけると見て外側に広がっては、各時間ステップに殺到し、そして最後のポイントまで広がりは我々が見つける必要があるということ遠い点です。そのような説明は説明するための画像のセット以下、ビット抽象的かもしれません。我々は層を通過し、各ポイントは最終的にトラバース、この時点で完了します我々はポイントを打つ必要があることを最後のポイントです。
コード
public static int maxDistance(int[][] grid) {
// 对应当前坐标周围的四个坐标
int[] aroundX = {0,0,1,-1};
int[] aroundY = {1,-1,0,0};
// 记录所有陆地区域的点
Queue<int[]> queueLand = new ArrayDeque<int[]>();
int colLength = grid.length;
int rowLength = grid[0].length; // 因为grid中每个元素的长度都相同,这里取第一个
for (int i = 0; i < colLength; i++) {
for (int j = 0; j < rowLength; j++) {
if(grid[i][j] == 1){
queueLand.offer(new int[]{i,j});
}
}
}
// 循环各个陆地 向外扩散 这里运用队列先进先出的特性
boolean isAllLandOrOcean = false;
int[] maxPoint = null;
while (!queueLand.isEmpty()){
maxPoint = queueLand.poll(); // 取出第一个点位的值并从队列中删除
// 遍历周围的四个点 以当前区域对X,Y坐标进行增减可得到周围的四个点
for (int i = 0; i < 4 ; i++) {
int newX = maxPoint[0] + aroundX[i];
int newY = maxPoint[1] + aroundY[i];
// 只对海洋区域的点位操作
if(newX > -1 && newX < colLength && newY > -1 && newY < rowLength && grid[newX][newY] == 0){
isAllLandOrOcean = true; // 能进入这里说明队列肯定不为空且存在未海洋区域的点
// 修改海洋区域的点位为距离最近的陆地的距离 从陆地点位向外扩散 每次以当前节点的值+1
grid[newX][newY] = grid[maxPoint[0]][maxPoint[1]] + 1;
// 把点位加到队列中进行下一轮循环
queueLand.offer(new int[]{newX,newY});
}
}
}
if(maxPoint == null || ! isAllLandOrOcean){
return -1;
}
return grid[maxPoint[0]][maxPoint[1]] - 1;
}