◀ THE GRIND — 1-D DYNAMIC PROGRAMMING

House Robber II

MEDIUM✓ CHIP-TIMEDLC #213 — FULL STATEMENT ↗

The drill: The same street of houses, but now it loops into a circle — the first and last house are neighbors too. Maximize the non-adjacent haul under that wraparound rule.

THE BRIEFING — THE FULL DRILL, IN MY OWN WORDS

The same row of houses returns, but now the street bends into a circle — the first house and the last house count as neighbors too, on top of every ordinary adjacent pair.

The same no-two-adjacent rule applies under that wraparound: robbing both the first and the last house at once is exactly as forbidden as robbing any other neighboring pair.

The task is still a single maximum total haul, now respecting the circular constraint instead of the straight one.

EX 01
nums = [7]
7
SINGLE HOUSE, NO WRAPAROUND CONFLICT
EX 02
nums = [5, 5]
5
TWO HOUSES ARE ALWAYS ADJACENT BOTH WAYS
EX 03
nums = [3, 10, 4]
10
MIDDLE HOUSE BEATS EITHER END
THE HINTS — TAKE ONLY WHAT YOU NEED
HINT 1 THE NUDGE

The circle adds exactly one new constraint over a straight street: the first and last house can't both be robbed. What does that split the problem into?

HINT 2 THE STRUCTURE

Either the first house is off the table, or the last house is — run the ordinary street version on both cuts of the circle and see which cut wins.

HINT 3 ONE STEP FROM THE ANSWER

Solve the linear house-robber on nums[0..n-2] and again on nums[1..n-1], then take the larger of the two totals — the wraparound is handled entirely by which end you drop.

COACH'S BOARD — THE PATTERN, STEP BY STEP
THE TWO CUTSPATTERN · TWO LINEAR PASSESnums = [2, 3, 2] (circular)
2
3
2
CUT RESULTS
— empty —
STEP 1

The street bends into a circle — house 0 and house 2 count as neighbors too, so both can't be robbed.

STEP 1 / 7 · ← → WORK TOO
THE SPLITS — TWO PACES, TWO LANGUAGES
grind/house-robber-ii.pyRACE PACE
LANG ▸
PACE ▸
class Solution:
    def rob(self, nums: List[int]) -> int:
        if len(nums) == 1:
            return nums[0]

        def line(row: List[int]) -> int:          # O(1)-space rolling DP
            prev2, prev1 = 0, 0
            for x in row:
                prev2, prev1 = prev1, max(prev1, prev2 + x)
            return prev1

        return max(line(nums[:-1]), line(nums[1:]))
TIME O(N)SPACE O(1)PYTHON · RACE PACE · 12 LN

✓ CHIP-TIMED — ALL 4 SOLUTIONS RAN GREEN AGAINST SELF-AUTHORED CASES IN CI · JDK 21 · CPYTHON 3.12 · NOTHING PUBLISHES RED