本文是个人的leetcode刷题笔记,记录做题的题解以及思想,方便往后的复习,题目如下:题目链接
题解思路:双标记法,看到题目第一反应是使用暴力解法进行操作,但仔细思考后发现每次置零后会影响到其他行列的变换,此时额外的空间使用则成为解题的关键。
方法①:使用两个bool数组分别记录该行和列是否拥有零数值,在对原矩阵遍历完成后,再根据bool数组对原矩阵进行操作,此时避免覆盖写0。
方法②:是方法一的改进,使用两个数组空间还是太多了,此时考虑使用原矩阵的首行首列作为0值记录数组,因为当该行该列拥有0时,首位会进行置零,此时可以进行记录不会影响到首行首列的其他数值,同时还需要使用两个额外的变量进行记录第一行和第一列是否拥有0数值,需要在最后进行置零,覆盖原记录。
func setZeroes(matrix [][]int) {
//使用两个标记变量法,是开辟空间法的变种
row:=len(matrix)
col:=len(matrix[0])
row1:=false
col1:=false
for _,v:=range matrix{
//判断第一列有无0
if v[0]==0{
col1=true
break
}
}
for _,v:=range matrix[0]{
//判断第一行有无0
if v==0{
row1=true
break
}
}
//判断其他行列的0数值,并将其记录到第一行以及第一列中,因为当前数值会影响到第一行第一列,故相对应的位置为0并没有影响,并可以用作记录空间
for i:=1;i<row;i++{
for j:=1;j<col;j++{
if matrix[i][j]==0{
matrix[i][0]=0
matrix[0][j]=0
}
}
}
//给除了第一行第一列赋值
for i := 1; i < row; i++ {
for j := 1; j < col; j++ {
if matrix[i][0] == 0 || matrix[0][j] == 0 {
matrix[i][j] = 0
}
}
}
//根据之前的判断,观察第一列第一行是否有0,并进行修改
if row1{
for i:=0;i<col;i++{
matrix[0][i]=0
}
}
if col1{
for i:=0;i<row;i++{
matrix[i][0]=0
}
}
}
方法③:单标记法,是方法②的一种改进方法,我们可以看到,其实在方法②中矩阵的(0,0)位置是没有表示任何内容的,此时(0,0)位置可以用于记录第一行是否拥有0,即相对方法②少用了一个额外的空间,同时为了防止(0,0是记录值)首行被提前赋值覆盖,需要使用行倒序进行操作。
func setZeroes(matrix [][]int) {
//单标记法,跟双标记法类似,只是用一个变量标记,使用数组第一个元素进行另外一个标记,同时为了防止列标记被首位提前覆盖,所以需要倒循环覆盖
row:=len(matrix)
col:=len(matrix[0])
col1:=false
//先按列循环,找出第一列有无0值
for _,v:=range matrix{
if v[0]==0{
col1=true
}
//同时在列中按照行进行循环,找出每行,列中是否有0值
for j := 1; j < col; j++ {
if v[j] == 0 {
v[0] = 0
matrix[0][j] = 0
}
}
}
//最后为了防止第一行被提前更新,故需要从后面的行开始赋值
for i:=row-1;i>=0;i--{
for j:=1;j<col;j++{
if matrix[i][0]==0||matrix[0][j]==0{
matrix[i][j]=0
}
}
if col1 {
matrix[i][0] = 0
}
}
}