System Software Engineer · Screening / VO Coding

Nvidia 二维种树题:四邻限制、贪心边界与最多棵追问

Nvidia 面经中的 0/1 地块种树:新树不能与旧树或新树四方向相邻。本文先给可行且极大的训练解,再区分最多棵目标。

题目重点:Nvidia 面经中的 0/1 地块种树:新树不能与旧树或新树四方向相邻。本文先给可行且极大的训练解,再区分最多棵目标。

题意与假设

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

  • 训练版返回一组新树坐标,不修改输入;行优先扫描能种就种,得到极大可行集合。极大指再不能追加,不代表数量最多。
  • 网格必须为非空矩形 0/1;原有树之间即使相邻也不删除,因为约束针对新栽树。
  • 若实际题目要求最多能种几棵或输出所有最优布局,本训练实现不满足,需要换成最大独立集算法。

解题路线

  1. 复制网格状态。行优先扫描每个空格,查看上、下、左、右;若四邻都没有已有或新栽的树,就种一棵并记下坐标。
  2. 由于每次种树前都检查四邻,输出不会有新树与旧树或两棵新树四邻冲突;扫描结束后所有剩余空格至少挨着一棵树,所以结果是极大的。
  3. 若面试官要求最大数量,先筛出不挨旧树的候选格;这些格构成网格二分图。最大独立集数量可由候选点数减最大匹配得到,不能继续把简单贪心当最优解。

手动走一遍

网格 [[0,0,0],[0,0,1]] 中,行优先贪心先种 (0,0),其余可行位置受约束,最后只种 1 棵;但选择 (0,1) 与 (1,0) 能种 2 棵。这个反例说明必须先问“任意可行布局”还是“最多棵”。

Python 参考实现

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

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

def choose_tree_positions(grid):
    """Row-major maximal placement; not guaranteed to maximize tree count."""
    if not grid or not grid[0] or any(len(row) != len(grid[0]) for row in grid):
        raise ValueError("grid must be nonempty and rectangular")
    if any(cell not in (0, 1) for row in grid for cell in row):
        raise ValueError("grid cells must be 0 or 1")
    rows, cols = len(grid), len(grid[0])
    planted = [row.copy() for row in grid]
    positions = []
    for row in range(rows):
        for col in range(cols):
            if planted[row][col] != 0:
                continue
            if any(
                0 <= row + dr < rows
                and 0 <= col + dc < cols
                and planted[row + dr][col + dc] == 1
                for dr, dc in ((1, 0), (-1, 0), (0, 1), (0, -1))
            ):
                continue
            planted[row][col] = 1
            positions.append((row, col))
    return positions

复杂度

R×C 个格各检查至多四邻,训练版时间 O(RC)、复制网格空间 O(RC)、输出最多 O(RC)。最大化版本需要构造候选格图并求最大匹配,复杂度高于一次贪心扫描。

易错点与追问

容易失分的边界

  • 只检查已有树,不把刚栽的新树写入状态,可能选出相邻的两棵新树。
  • 把对角相邻也判为冲突,强加了题目没有的限制。
  • 把极大误说成最大,忽略行优先贪心可能少种树的反例。
  • 原有树彼此相邻时直接拒绝整张图;题目只约束新栽的树,是否要求旧图合法应先问。

继续深挖

  • 若只问哪些单独格子可种,只需输出所有不挨已有树的空格;这些格子不能保证可以同时全种。
  • 若要求最多棵,利用棋盘黑白染色将候选格构成二分图,再由最大匹配推最大独立集。
  • 若有禁种地块、不同树种间距或八方向冲突,图结构和最优算法要重新分析。
✓已复制微信号!