题意:
Given a m x n matrix, if an element is 0, set its entire row and column to 0. Do it in place.
Follow up:
Did you use extra space?
A straight forward solution using O(mn) space is probably a bad idea.
A simple improvement uses O(m + n) space, but still not the best solution.
Could you devise a constant space solution?
思路:最开始想到的方法是直接在矩阵上设置标志位,但是发现一个问题就是,这个标志位设为多少合适,毕竟题目没有说明这个矩阵的类型,所以pass。之后参考了一些代码,发现都是利用第一行和第一列来作为标志,对整个矩阵扫描两遍,第一遍设置标志位,如果这一列/行中存在0,则对应标志位设0,第二遍赋0,如果第一行/列某个标志数为0,则这一行/列为0,但是又有一个问题是这个行列标志位自身要不受自身行列中0的影响,所以很多做法是先抛开第一行和第一列,开始时增加两个标志位来判断第一行和第一列是否为全0,处理完后再来处理第一行/列。
参考方法一:
class Solution:
# @param matrix, a list of lists of integers
# RETURN NOTHING, MODIFY matrix IN PLACE.
def setZeroes(self, matrix):
first_col = reduce(lambda acc, i: acc or matrix[i][0] == 0, xrange(len(matrix)), False)
first_row = reduce(lambda acc, j: acc or matrix[0][j] == 0, xrange(len(matrix[0])), False)
for i in xrange(1, len(matrix)):
for j in xrange(1, len(matrix[0])):
if matrix[i][j] == 0:
matrix[i][0], matrix[0][j] = 0, 0
for i in xrange(1, len(matrix)):
for j in xrange(1, len(matrix[0])):
if matrix[i][0] == 0 or matrix[0][j] == 0:
matrix[i][j] = 0
if first_col:
for i in xrange(len(matrix)):
matrix[i][0] = 0
if first_row:
for j in xrange(len(matrix[0])):
matrix[0][j] = 0
还有一种方法就更为巧妙一些,每行/列的第一位还是标志位,但是它把第一行标志位当做和其他行放在一起,普通化处理。在处理前,如果它为1,说明这一列没有0,即这一标志位不用处理,如果它为0,说明这一列全为0,这一标志位也不用处理。这段代码就只需要考虑第一列的标志位,所以添加了is_zero作为全局标志,如果开始时,这一列有0,则最后结尾时把这一列标志位全赋0。还有就是for执行的顺序,第一次循环是自上而下的,标志位不受影响,赋值时的循环就是自下而上了,也是为了标志位不受影响,方法二:
class Solution(object):
def setZeroes(self, matrix):
"""
:type matrix: List[List[int]]
:rtype: void Do not return anything, modify matrix in-place instead.
"""
is_zero, row, col = False, len(matrix), len(matrix[0])
for i in xrange(row):
if matrix[i][0] == 0:
is_zero = True
for j in xrange(1, col):
if matrix[i][j] == 0:
matrix[i][0] = matrix[0][j] = 0
for i in reversed(xrange(row)):
for j in xrange(1, col):
if matrix[i][0] == 0 or matrix[0][j] == 0:
matrix[i][j] = 0
if is_zero:
matrix[i][0] = 0