1. 程式人生 > >LeetCode日常刷題542、

LeetCode日常刷題542、

542. 01 矩陣

給定一個由 0 和 1 組成的矩陣,找出每個元素到最近的 0 的距離。

兩個相鄰元素間的距離為 1 。

示例 1:
輸入:

0 0 0
0 1 0
0 0 0

輸出:

0 0 0
0 1 0
0 0 0

示例 2:
輸入:

0 0 0
0 1 0
1 1 1

輸出:

0 0 0
0 1 0
1 2 1

注意:

  1. 給定矩陣的元素個數不超過 10000。
  2. 給定矩陣中至少有一個元素是 0。
  3. 矩陣中的元素只在四個方向上相鄰: 上、下、左、右。

這道題應用的是廣度優先搜尋(BFS演算法),是最簡便的圖的搜尋演算法之一,這一演算法也是很多重要的圖的演算法的原型。

BFS演算法,一般是用佇列實現,先進先出。其主要原理是,使用佇列儲存未被查詢過的結點。

最簡單的例子就是:我們丟了東西,首先會在自己的周圍找,如果周圍沒找到,那麼就會想遠一點的地方,然後去找。

下面是BFS演算法的常用模組:

BFS:
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
const int maxn=100;
bool vst[maxn][maxn]; // 訪問標記
int dir[4][2]={0,1,0,-1,1,0,-1,0}; // 方向向量

struct State // BFS 佇列中的狀態資料結構
{
int x,y; // 座標位置
int Step_Counter; // 搜尋步數統計器
};

State a[maxn];

bool CheckState(State s) // 約束條件檢驗
{
if(!vst[s.x][s.y] && ...) // 滿足條件
return 1;
else // 約束條件衝突
return 0;
}

void bfs(State st)
{
queue <State> q; // BFS 佇列
State now,next; // 定義2 個狀態,當前和下一個
st.Step_Counter=0; // 計數器清零
q.push(st); // 入隊
vst[st.x][st.y]=1; // 訪問標記
while(!q.empty())
{
now=q.front(); // 取隊首元素進行擴充套件
if(now==G) // 出現目標態,此時為Step_Counter 的最小值,可以退出即可
{
...... // 做相關處理
return;
}
for(int i=0;i<4;i++)
{
next.x=now.x+dir[i][0]; // 按照規則生成下一個狀態
next.y=now.y+dir[i][1];
next.Step_Counter=now.Step_Counter+1; // 計數器加1
if(CheckState(next)) // 如果狀態滿足約束條件則入隊
{
q.push(next);
vst[next.x][next.y]=1; //訪問標記
}
}
q.pop(); // 隊首元素出隊
}
 return;
}

int main()
{
......
 return 0;
}

對於此題,我們用java來寫。我們分析道,題目要求必須含有零,那麼我們可以把所有0入隊,把1置為MAX_VALUE,然後把最靠近0的1的距離算出來,然後將他們入隊,再算距離最靠近0的1的1的距離算出來,依次處理

class Solution {
    public List<List<Integer>> updateMatrix(List<List<Integer>> matrix) {  
        if (matrix == null || matrix.size() == 0)  
            return matrix;  
        int m = matrix.size();  
        int n = matrix.get(0).size();  
        Queue<int[]> q = new LinkedList<>();  
        for (int i = 0; i < m; i++)  
            for (int j = 0; j < n; j++) {  
                // 把0元素加入佇列中,以備波及影響周圍元素  
                if (matrix.get(i).get(j) == 0)  
                    q.offer(new int[] { i, j });  
                else  
                    // 設為最大值,方便求0元素影響值  
                    matrix.get(i).set(j, Integer.MAX_VALUE);  
            }  
        // 上下左右  
        int[][] dirs = { { -1, 0 }, { 1, 0 }, { 0, -1 }, { 0, 1 } };  
        while (!q.isEmpty()) {  
            int cell[] = q.poll();  
            for (int[] d : dirs) {  
                int row = cell[0] + d[0];  
                int col = cell[1] + d[1];  
                if (row < 0 || row >= m || col < 0 || col >= n)  
                    continue;  
                // 上下左右取到的值  
                int value = matrix.get(row).get(col);  
                int tmp = matrix.get(cell[0]).get(cell[1]) + 1;  
                // 如果value小,那說明之前已經更新過,不是max  
                if (value <= tmp)  
                    continue;  
                q.offer(new int[] { row, col });  
                matrix.get(row).set(col, tmp);  
      
            }  
      
        }  
      
        return matrix;  
    }  
}

def updateMatrix(self, matrix):
    if not matrix or not matrix[0]: return matrix
    M, N = len(matrix), len(matrix[0])
     
    cur = set()
    for i in range(M):
        for j in range(N):
            if matrix[i][j] == 1:
                for ni, nj in [(i - 1, j), (i + 1, j), (i, j - 1), (i, j + 1)]:
                    if -1 < ni < M and -1 < nj < N and matrix[ni][nj] == 0:
                        cur.add((i, j))
                        matrix[i][j] = -1
                        break
    distance = 1
    while cur:
        nxt = set()
        distance += 1
        for i, j in cur:
            for ni, nj in [(i - 1, j), (i + 1, j), (i, j - 1), (i, j + 1)]:
                if -1 < ni < M and -1 < nj < N and matrix[ni][nj] == 1:
                    matrix[ni][nj] = distance
                    nxt.add((ni, nj))
        cur = nxt
     
    for i in range(M):
        for j in range(N):
            if matrix[i][j] == -1:
                matrix[i][j] = 1
     
    return matrix