SWE · Coding

Meta 矩阵置零:首行首列标记与原始状态

遇原始零将整行整列归零,复用矩阵边界作标记并避免新零继续传播。

题目重点:遇原始零将整行整列归零,复用矩阵边界作标记并避免新零继续传播。

题意与假设

这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。

  • 训练可变矩形,各行不是同一list别名;原始值0触发置零,负数等其他值保持除受影响位置。空矩阵原样返回。

解题路线

  1. 先保存原首行有零与原首列有零两个bool。内区间发现原0,把matrix[r][0]与matrix[0][c]置0作为行列标记。
  2. 随后只遍历内区间,根据行/列标記清零。首行首列最后依据两个原始bool清零,不能提前清使所有标记变0。
  3. 不立即把发现0的整行整列清掉,否则后来读取的新0会继续触发,可能清空本不应受影响的全矩阵。标记阶段与应用阶段分开才保留原始集合。
  4. 首格[0][0]不能同时编码首行与首列独立状态,因此两个bool必要。单行/单列内循环为空,最后边界处理仍正确。

手动走一遍

[[1,2,3],[4,0,6],[7,8,9]]得到[[1,0,3],[0,0,0],[7,0,9]],不是全0。首行有零仅代表该行全部清,并列标记影响对应列,不代表首列也全部清。

Python 参考实现

下面的代码按上文假设实现,适合本地运行并追加自己的测试用例。

代码区可横向滚动;使用键盘时,先聚焦代码区再按方向键查看。

def set_zeroes(matrix):
    """Mutable rectangular matrix, original zeros clear whole row and column."""
    if not matrix or not matrix[0]:return matrix
    rows,cols=len(matrix),len(matrix[0])
    if any(len(row)!=cols for row in matrix):raise ValueError('ragged matrix')
    first_row=any(v==0 for v in matrix[0]);first_col=any(matrix[r][0]==0 for r in range(rows))
    for r in range(1,rows):
        for c in range(1,cols):
            if matrix[r][c]==0:matrix[r][0]=0;matrix[0][c]=0
    for r in range(1,rows):
        for c in range(1,cols):
            if matrix[r][0]==0 or matrix[0][c]==0:matrix[r][c]=0
    if first_row:
        for c in range(cols):matrix[0][c]=0
    if first_col:
        for r in range(rows):matrix[r][0]=0
    return matrix

复杂度

O(RC)时间/O(1)算法辅助空间,输入矩阵即输出;若先copy输入返回新矩阵则总额外O(RC)。检验按原始零行/列集合构造oracle而非再实现同样marker逻辑。

易错点与追问

容易失分的边界

  • 标记未完成就清首行首列,所有行列都被误标。
  • [0][0]一个值混合两个独立边界状态。

继续深挖

  • 如果不能改输入,怎样用row/col集合输出新矩阵并计空间?
  • 矩阵行对象共享别名时为什么原地逐行修改会跨行影响?
✓已复制微信号!