1. 程式人生 > >(佇列應用——廣度優先遍歷)01矩陣

(佇列應用——廣度優先遍歷)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。
矩陣中的元素只在四個方向上相鄰: 上、下、左、右。

題目分析

題目很容易理解,即是找矩陣中各個元素與0元素的距離。對於0元素自身來說,這個距離自然就是0了,而對於非0元素來說,它對於不同的0元素距離是可能不同的,那麼它最終的距離當然是取這些距離中的最小值了。
這樣一來,如果某個元素與0元素相鄰(指與0元素上下左右相鄰),那麼該元素與0元素的距離則是1了,如果某個元素不與0元素相鄰,那麼該元素與0元素的距離就應當取該元素上下左右相鄰元素各自與0元素的距離值中的最小值加一,好了,那麼這道題該怎麼做呢?如果用最笨的方法,即是對每一個元素的上下左右四個方向慢慢擴充套件,如果碰到0了那麼距離也就出來了,不過這種方法顯然複雜度是非常高的。
因此就考慮使用BFS來完成,廣度優先是使用佇列,這裡的想法是,先將所有0元素的座標壓入佇列中,然後再取出每個0元素的座標,並且遍歷該座標的上下左右,很顯然,如果上下左右中某個點的值非0,那麼就應當讓其為1了,這樣一直遍歷結束後,就可以把所有與0相鄰的非0元素置為1,那麼與0不相鄰的元素怎麼辦呢?
這時候只需將與0元素相鄰的點的座標再壓入佇列中,再遍歷這些與0元素相鄰的點的四周,那麼其四周就會存在與0元素不相鄰的點,再將這與0元素相鄰的點的四周的點座標也壓入佇列中…這樣就可以把所有與0不相鄰的點也遍歷到,而對於與0元素不相鄰的點,前面說過,與0元素不相鄰的點與0元素的距離是等於其四周各點與0元素距離值中的最小值加1,這是一個取最小值的過程,從0元素開始到與0元素相鄰的元素再慢慢往外擴充套件…簡單來說,從0元素開始,遍歷其四周,如果其四周某一點與0元素的距離值大於了當前元素值+1(此時的當前元素值代表當前位置與0元素的距離),那麼就應當將其置為當前元素值+1,並且再把遍歷過的點再壓入佇列中,然後再遍歷該點,此時該點的值已經是與0元素的距離值了,如果該點四周某元素值大於該點值+1,那麼也將其置為該點值+1…
此外,BFS中往往需要使用相應的變數來防止同一個元素被多次訪問,那麼這裡是否需要呢?實際上是不需要的,因為在這種問題下恰恰是需要同一個元素被多次(2≤n≤4)訪問,直到其恰好等於該點四周最小值+1,此時該點就不會再壓入棧內了,這樣也不會造成同一個點重複壓入佇列從而造成無限迴圈的情況。
除此之外,如前所述,每個遍歷後的點需要判斷其四周各點與0元素的距離值是否大於該點值+1,那麼對於未被處理過的點,在一開始就應當將其置為一個較大的值,這裡直接將其置為INT_MAX。

程式如下:

vector<vector<int>> updateMatrix(vector<vector<int>>& matrix) {
        queue<int>q;
        int row=matrix.size();
        int col=matrix[0].size();
        for(int i=0;i<row;i++)
            for(int j=0;j<col;j++)
            {
                if(matrix[i][j])matrix[i][j]=INT_MAX;    //非0元素置為最大值
                else q.push(i*col+j);      //先將0元素座標壓入佇列中
            }
        while(!q.empty())
        {
            int temp=q.front();
            q.pop();
            int r=temp/col;     //獲取當前元素的行值
            int c=temp%col;     //獲取當前元素的列值
            if(r+1<row&&matrix[r+1][c]>matrix[r][c]+1) //down
            {
                matrix[r+1][c]=matrix[r][c]+1;
                q.push((r+1)*col+c);
            }
            if(r>0&&matrix[r-1][c]>matrix[r][c]+1)  //up
            {
                matrix[r-1][c]=matrix[r][c]+1;
                q.push((r-1)*col+c);
            }
            if(c+1<col&&matrix[r][c+1]>matrix[r][c]+1)  //right
            {
                matrix[r][c+1]=matrix[r][c]+1;
                q.push(r*col+c+1);
            }
            if(c>0&&matrix[r][c-1]>matrix[r][c-1]+1)  //left
            {
                matrix[r][c-1]=matrix[r][c]+1;
                q.push(r*col+c-1);
            }        
        }
        return matrix; 
    }