题目重点:按对角线分组,每条从上到下打印,明确行列坐标与反对角线定义。
题意与假设
这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。
- 训练选择反对角线r+c固定,按r+c从小到大,每条r递增(从上到下);返回每条list。题目未给完整坐标约定,若要求主对角线r−c则需调整。
- 不同于每隔一条反向的zigzag,不能看到diagonal就默认交替方向。
- 另一种练习合同为zigzag:偶数r+c反向、奇数正向。先给小矩阵预期结果确认方向。
解题路线
- 对total=0..R+C−2,合法row下界max(0,total−C+1)、上界min(R−1,total),column=total−row,按row升序收集。
- 上下界来自0≤col<C与0≤row<R交集,支持长方形无需转置。每格恰好归一个total,不重复不遗漏。
- 同方向规则在所有total保持,不根据奇偶reverse。输出扁平还是每条一行是格式层,核心坐标次序不变。
- 如果从左上向右下主对角线,改用col−row常量和起点集合;必须给小矩阵预期输出来消除语言含混。
- diagonal_zigzag复用同向分组,对偶数total的整条结果逆转后拼接。每元素仍恰被处理一次,奇偶方向约定必须先对齐。
手动走一遍
[[1,2,3],[4,5,6]]反对角线同方向输出[1]、[2,4]、[3,5]、[6];zigzag会反转某些条,不能用它替代。 同一矩阵zigzag版本为[1,2,4,5,3,6],total2的[3,5]反向成[5,3]。
Python 参考实现
下面的代码按上文假设实现,适合本地运行并追加自己的测试用例。
代码区可横向滚动;使用键盘时,先聚焦代码区再按方向键查看。
def diagonal_rows(matrix):
"""Training anti-diagonals row+col constant; each diagonal top-to-bottom.
Return per-diagonal lists, not alternating zigzag or main diagonals.
"""
if not matrix or not matrix[0]:return []
rows,cols=len(matrix),len(matrix[0])
if any(len(row)!=cols for row in matrix):raise ValueError('ragged matrix')
result=[]
for total in range(rows+cols-1):
result.append([matrix[row][total-row] for row in range(max(0,total-cols+1),min(rows-1,total)+1)])
return result
def diagonal_zigzag(matrix):
"""Standard anti-diagonals, alternate; even sum reversed, flat output."""
result=[]
for total,values in enumerate(diagonal_rows(matrix)):
result.extend(reversed(values) if total%2==0 else values)
return result
复杂度
O(RC)元素工作加O(R+C)条数,总O(RC)非空矩阵,输出O(RC),不含输出的索引状态O(1)。不用构造sort全部坐标,独立测试可排序(r+c,r)坐标对照。 zigzag构造分组和扁平输出,峰值O(RC),不能把这份实现说成O(1)辅助空间。
易错点与追问
容易失分的边界
- 把Zigzag熟题顺序直接照搬。
- 正方形专用上界导致矩形越界或漏右侧。
继续深挖
- 输入是各行不同长度的ragged list时,当前矩形公式不适用,可按r+c分桶但改变空间。
- 流式输出一条一条可用generator,峰值空间按一条最大长度。
