每天一道LeetCode-----给定一个矩阵,如果某个元素是0,就将所在行所在列上所有元素否置0
Set Matrix Zeroes
原題鏈接Set Matrix Zeroes
給定一個(gè)m × n矩陣,如果矩陣中某個(gè)元素是0,那么就將它所在的行,所在的列上的所有元素都變成0。要求空間復(fù)雜度在O(1),也就是說在原矩陣上就修改
在原矩陣上做修改無非兩種方法
一種是使用遞歸,即發(fā)現(xiàn)某個(gè)元素是0,就把對(duì)應(yīng)行對(duì)應(yīng)列的每個(gè)元素賦值為0,然后遞歸的以它所在這一行,這一列的每個(gè)元素為起點(diǎn),依次做同樣的事情
這種方法在遞歸的過程中極易出錯(cuò),而且對(duì)于很多邊界條件無法很好的控制
另外一種是先不著急對(duì)矩陣的元素進(jìn)行更改,只記錄哪幾行,哪幾列的元素應(yīng)該被賦值成0。不過需要在原矩陣上記錄,而不能使用額外的空間
這種方法唯一需要解決的就是如何記錄在原矩陣中。
綜上,可以看出使用第二種方法最為合適,但是,要怎么保存都有哪幾行,哪幾列的元素應(yīng)該被置成0呢。試想,在遍歷完矩陣后,矩陣的某些位置應(yīng)該是被改變的,這些被改變的位置標(biāo)記著對(duì)應(yīng)行,或者是對(duì)應(yīng)列的所有元素是否應(yīng)該被置成0。如果把行和列分開來記錄,那么可以說
應(yīng)該有一行的元素記錄對(duì)應(yīng)列是否被置為0,同時(shí)也應(yīng)該有一列元素記錄對(duì)應(yīng)行是否被置為1
那么,只需要將原矩陣中的某個(gè)行和某一列用來記錄就可以了,具體哪一行哪一列不固定,不過正常來說,選擇第0行記錄每一列是否應(yīng)該被置為0,選擇第0列記錄每一行是否應(yīng)該被置為0比較合適
那么,程序唯一需要做的就是遍歷一遍矩陣,如果某個(gè)元素值為0,就將第0行的對(duì)應(yīng)列置為0,同時(shí)也要將第0列的對(duì)應(yīng)行置為0。這樣,當(dāng)遍歷結(jié)束后,只需要再遍歷一遍第0行,把是0的位置的那一列都變?yōu)?,同時(shí)遍歷一遍第0列,把是0的位置的那一行都變?yōu)?.
但是,有個(gè)問題!
如果遍歷的時(shí)候碰巧第0行的某個(gè)元素的值為0,那么按照上面的做法,應(yīng)該是
將第0行的當(dāng)前列(還是這個(gè)元素所在位置)置為0。這一步驟沒什么問題
將第0列的當(dāng)前行(注意當(dāng)前行是0)置為0,也就是將第0行第0列這個(gè)位置置為0
第二步會(huì)出現(xiàn)什么問題?倘若第0行第0列的那個(gè)位置被置為0,那么再更改矩陣元素時(shí),第0行和第0列的所有元素將變?yōu)?,最終導(dǎo)致矩陣所有元素都變?yōu)?!
第0列的某個(gè)元素的值為0也是同理。
所以這種方法是不可取的,不過只是對(duì)于處理第0行和第0列的所有元素不可取,換句話說只是對(duì)第0行第0列的那個(gè)元素不可取(注意第0行和第0列與第0行第0列的區(qū)別)
那么程序無非要做的就是對(duì)上面問題單獨(dú)處理
只要是第0行的某個(gè)元素是0,那么就找個(gè)變量記錄第0行的所有元素應(yīng)該都被置為0
只要是第0列的某個(gè)元素是0,那么就找個(gè)變量記錄第0列的所有元素應(yīng)該都被置為0
當(dāng)然,對(duì)于第0行和第0列的置0操作都應(yīng)該被放在最后執(zhí)行,也就是放在將矩陣元素都大體改完之后執(zhí)行。不然,把第0行和第0列的所有元素都置為0了,那么如果再根據(jù)第0行和第0列判斷對(duì)應(yīng)列和對(duì)應(yīng)行是否應(yīng)該被置為0,結(jié)果只會(huì)另矩陣所有元素都變?yōu)?
另外,上述操作只是為了防止將第0行第0列的那個(gè)位置的元素置為0。
代碼如下
class Solution { public:void setZeroes(vector<vector<int>>& matrix) {if(matrix.empty() || matrix[0].empty())return;/* 記錄第0行的元素是否應(yīng)該被置為0 */bool oneRowZero = false;/* 記錄第0列的元素是否應(yīng)該被置為0 */bool oneColumnZero = false;for(int i = 0; i < matrix.size(); ++i){for(int j = 0; j < matrix[i].size(); ++j){if(matrix[i][j] == 0){/* 如果某個(gè)元素是0,就將第0行的對(duì)應(yīng)列,第0列的對(duì)應(yīng)行置為0 */matrix[i][0] = matrix[0][j] = 0;/* 如果是第0行的元素是0,那么就任務(wù)第0行應(yīng)該被置為0 */if(i == 0)oneRowZero = true;/* 同理第0列 */if(j == 0)oneColumnZero = true;} } } /* 遍歷矩陣第0列,如果第0列的某個(gè)元素是0,就將對(duì)應(yīng)行的元素置0 *//* 這里沒有考慮第0行第0列 */for(int i = 1; i < matrix.size(); ++i){if(matrix[i][0] == 0){for(int j = 1; j < matrix[i].size(); ++j)matrix[i][j] = 0;}}/* 同理,遍歷矩陣第0行,將對(duì)應(yīng)列元素置0 */for(int j = 1; j < matrix[0].size(); ++j){if(matrix[0][j] == 0){for(int i = 1; i < matrix.size(); ++i)matrix[i][j] = 0;}}/* 設(shè)置第0行 */if(oneRowZero){for(int j = 0; j < matrix[0].size(); ++j)matrix[0][j] = 0;}/* 設(shè)置第0列 */if(oneColumnZero){for(int i = 0; i < matrix.size(); ++i)matrix[i][0] = 0;}} }本題要求空間復(fù)雜度在O(1),所以不能重新開辟一塊矩陣作為更新后的值。只能想辦法在原矩陣上做修改,而對(duì)于遞歸而言,每次遞歸都要遞歸一整行和一整列,遞歸深度過深,容易出錯(cuò)。那么就只能在原矩陣中找一些位置記錄都有哪幾行哪幾列應(yīng)該被置為0,這個(gè)過程中需要考慮如果將第0行第0列那個(gè)位置置為0的話,會(huì)導(dǎo)致整個(gè)矩陣變?yōu)?,所以需要單獨(dú)考慮。
與50位技術(shù)專家面對(duì)面20年技術(shù)見證,附贈(zèng)技術(shù)全景圖總結(jié)
以上是生活随笔為你收集整理的每天一道LeetCode-----给定一个矩阵,如果某个元素是0,就将所在行所在列上所有元素否置0的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 每天一道LeetCode-----使用最
- 下一篇: IA-32 Intel手册学习笔记(三)