LeetCode日常刷題542、
阿新 • • 發佈:2018-12-31
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
注意:
- 給定矩陣的元素個數不超過 10000。
- 給定矩陣中至少有一個元素是 0。
- 矩陣中的元素只在四個方向上相鄰: 上、下、左、右。
這道題應用的是廣度優先搜尋(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