542.01マトリックス分析

トピックの説明:

0と1の行列マットが与えられた場合、同じサイズの行列を出力します。ここで、各セルは、マット内の対応する位置にある要素から最も近い0までの距離です。
2つの隣接する要素間の距離は1です。

例1:

ここに画像の説明を挿入

入力:mat = [[0,0,0]、[0,1,0]、[0,0,0]]
出力:[[0,0,0]、[0,1,0]、[0 、0,0]]

例2:

ここに画像の説明を挿入

入力:mat = [[0,0,0]、[0,1,0]、[1,1,1]]
出力:[[0,0,0]、[0,1,0]、[1 、2,1]]

この質問は一般的な幅優先検索タイプです。幅優先検索の2つのテンプレートについては、
BFS使用キューに精通し、検索されていない各ポイントを順番にキューに入れてから、キューをポップアップしてください。のヘッド要素は、現在のトラバーサルポイントです。BFSには、合計2つのテンプレートがあります。

  • 1.現在トラバースされているレイヤーを判別する必要がない場合、BFSテンプレートは次のようになります。
while queue 不空:
    cur = queue.pop()
    for 节点 in cur的所有相邻节点:
        if 该节点有效且未访问过:
            queue.push(该节点)
  • 2.現在トラバースされているレイヤーを確認する場合、BFSテンプレートは次のとおりです。
    レベルはここに追加され、バイナリツリーのどのレベルが現在トラバースされているかを示します。これは、グラフで実行されたステップ数としても理解できます。サイズは、現在のトラバーサルレイヤーにある要素の数、つまりキュー内の要素の数を示します。これらの要素を一度にトラバースします。つまり、現在のレイヤーのすべての要素を1ステップ外側に移動します。
level = 0
while queue 不空:
    size = queue.size()
    while (size -->0) {
    
    
        cur = queue.pop()
        for 节点 in cur的所有相邻节点:
            if 该节点有效且未被访问过:
                queue.push(该节点)
    }
    level ++;

そして、このトピックでは、幅優先の階層化されたアイデアを使用できます。タイトルに示されている例に関する限り、1にどのような状況があるかを確認できます。

  • 1.上、下、左、右の4方向に少なくとも1つの0があります
  • 2.上、下、左、右の4方向に0はなく、すべて1で囲まれており、1の少なくとも1つは最初のケースに準拠しています。

この考え方に従い、n * n行列を拡張し、
引き続き上記の考え方に従って、3番目、4番目、...n番目のケースを拡張します。

  • 3.上下左右の1で囲まれ、そのうちの少なくとも1つが2番目のケースと一致します
  • 4.上下左右の1で囲まれ、そのうちの少なくとも1つが3番目のケースに準拠している場合、
    次のタイプの行列を指定できます。
    ここに画像の説明を挿入

この種の行列は、私たちの階層的な考え方に従って描かれています。最初の層、つまり最外層はすべて0であることがわかります。考慮する必要はありません。最短経路はi-1です。つまり、1-1 = 0です
。2番目の層の1は少なくとも1つの0で囲まれ、最短経路はi-1 = 2-1 = 1などであるため、次のようにする必要があります。階層的な考えに従って質問によって与えられた行列を変換し、それをに変換します上記のタイプの行列の場合、各層を見つける方法は?
まず、0は気にしません。1で、その周りに少なくとも1つの0がある場合は、それらをキューに入れます。最初のレイヤーが終了すると、次の1を見つけ始めます。最初のレイヤーに隣接し、アクセスされていない場合は、エンキューします。パスの長さは2に設定できます。
一般的に、考え方は次のとおりです。

  • 1. 0でラップされたすべての1をエンキューし、同時にレベルを1に設定します
  • 2.最初のレイヤーによってラップされ、アクセスされていないすべての1をキューに入れ、レベルを2に設定します
  • 3.上記の2つのプロセスを繰り返します。常に、レベルを上げる必要があることに注意してください。

上記のアイデアでコードを見てください。コードには詳細なコメントがあることに注意してください。辛抱強く読んでください。
コードは次のとおりです。

import java.util.*;

/**
 * 题目:0 1矩阵
 * 题目编号:542
 * 题目链接:https://leetcode-cn.com/problems/01-matrix/
 */
public class 矩阵01_542 {
    
    
    /**
     * 是否还在矩阵中
     * 在:true
     */
    public static boolean inBound(int x, int y, int[][] grid) {
    
    
        if (x >= 0 && x < grid.length && y >= 0 && y < grid[0].length) {
    
    
            return true;
        } else return false;
    }

    public static int[][] updateMatrix(int[][] mat) {
    
    
        int row = mat.length;//行数
        if (row <= 0) return mat;
        int column = mat[0].length;//列数
        //定义上下左右四个移动方向
        int[] dx = {
    
    0, 0, -1, 1};
        int[] dy = {
    
    -1, 1, 0, 0};
        boolean[][] visted = new boolean[row][column];//存储
        Queue<int[]> queue = new LinkedList<>();//记录移动点的坐标
        for (int i = 0; i < row; i++) {
    
    //遍历整个棋盘,让第一层的1入队
            for (int j = 0; j < column; j++) {
    
    
                if (mat[i][j] == 0) {
    
    
                    visted[i][j] = true;
                }
                if (mat[i][j] == 1) {
    
    //首先把第一层的1放入队列
                    int count = 0;//用来记录上下左右有没有0,一旦发现有0就会计数
                    for (int index = 0; index < 4; index++) {
    
    
                        int next_x = i + dx[index];
                        int next_y = j + dy[index];
                        if (inBound(next_x, next_y, mat) && mat[next_x][next_y] == 0) {
    
    //第一层的1必定上下左右至少有一个0
                            count++;
                        }
                    }
                    if (count > 0) {
    
    //说明上下左右中至少一个0符合第一层的1的定义,可以入队 队列第一层
                        queue.add(new int[]{
    
    i, j});
                        visted[i][j] = true;


                    }
                }

            }
        }
        int level = 1;//由于第一层的1已经 入队,所以level设置为1
        while (!queue.isEmpty()) {
    
    
            int size = queue.size();
            while (size-- > 0) {
    
    //用来判断这一层是否结束
                int[] t = queue.poll();
                int x = t[0], y = t[1];
                mat[x][y] = level;
                //开始找下一层的信息
                for (int i = 0; i < 4; i++) {
    
    
                    int next_x = x + dx[i];
                    int next_y = y + dy[i];
                    if (inBound(next_x, next_y, mat) && !visted[next_x][next_y]) {
    
    
                        queue.add(new int[]{
    
    next_x, next_y});
                        visted[next_x][next_y] = true;
                    }
                }
            }
            level++;//每一层一旦遍历结束就加一层
        }
        return mat;
    }

    public static void print(int[][] mat) {
    
    
        for (int i = 0; i < mat.length; i++) {
    
    
            for (int j = 0; j < mat[0].length; j++) {
    
    
                System.out.print(mat[i][j] + " ");
            }
            System.out.println();//换行
        }
    }

    public static void main(String[] args) {
    
    
        int[][] mat = {
    
    {
    
    0, 0, 0}, {
    
    0, 1, 0}, {
    
    1, 1, 1}};
        print(mat);
        System.out.println("-------------------------------");
        print(updateMatrix(mat));
    }
}

おすすめ

転載: blog.csdn.net/zhiyikeji/article/details/123273846