SDE2 · OA Coding

Amazon OA:House Robber II 环形相邻约束怎样拆?

将不同时选择首尾转换为两条线性DP,处理单元素与常数辅助空间。

题目重点:将不同时选择首尾转换为两条线性DP,处理单元素与常数辅助空间。

题意与假设

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

  • 非负整数值,环中相邻房子不能同时选,可不选;首尾相邻。
  • 训练空数组0、单房可选、两房最多一房;这些边界是标准训练合同。

解题路线

  1. n≥2时合法解不能同时选0和n-1,因此至少排除一端。分别算[0,n-2]与[1,n-1]线性最大非相邻和,取max。
  2. 线性递推D[i]=max(D[i-1],D[i-2]+value[i]),两项对应不选与选当前;保留两个旧状态即可,不需要全DP数组。
  3. 两子问题可能重叠同一解,但只取最大不计数量,所以重复不影响正确性。每个合法环形解至少在一子问题,每个子问题解又是合法环形解。
  4. 单元素不能按排除端点两段都会空处理,独立返回本值;示例用索引范围不切片,才是真正O(1)辅助空间。

手动走一遍

训练[2,3,2]最大3不能选首尾2+2;[1,2,3,1]最大4;[5]返回5。

Python 参考实现

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

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

def maximum_nonadjacent_ring(values):
    """Nonnegative house values, first/last adjacent; single house may be chosen."""
    if any(v<0 for v in values):raise ValueError("nonnegative values required")
    if not values:return 0
    if len(values)==1:return values[0]
    def line(start,end):
        before2=before1=0
        for i in range(start,end):
            before2,before1=before1,max(before1,before2+values[i])
        return before1
    return max(line(0,len(values)-1),line(1,len(values)))

复杂度

O(n)时间、O(1)辅助状态,输出仅金额;重建所选下标需要保存决策或再遍历。

易错点与追问

容易失分的边界

  • 套线性DP选首尾。
  • 单房排除后返回0。
  • 用数组切片却声称无额外内存。

继续深挖

  • 要返回最优集合怎么重建?
  • 统计最优解数量怎样防两段重复?
  • 环上距离2内不能同选怎样分情况?
✓已复制微信号!