Dynamic Programming part 4, Sam's DP example 2: House Robber (2 choices)

*Prerequisite: The Modern Law of Dynamic Programming Part 1 & 2.

This tutorial is a part of the Data Structures and Algorithms class:

Step 0: is it a multi-stage decision making process problem?

lc 198 is it a dp problem

Step 1: solve the problem with pen and paper, then code DFS state tree

house robber step 1

lecture-34/house-robber.js
// Sam's DP, Leetcode #198: https://leetcode.com/problems/house-robber/description/

// step 1: full branch out
function robStep1 (nums) {

  const dfs = (i) => {

    if(i >= nums.length) return

    console.log('nums[i]]:', nums[i], i)

    dfs(i + 2) // house after adjacent
    dfs(i + 1) // adjacent house
  }

  dfs(0)
}
$ node house-robber.js
nums[i]]: 1 0
nums[i]]: 4 2
nums[i]]: 3 1
nums[i]]: 4 2
robStep1 [1,3,4]: undefined

Step 2: calculate the information asked, bottom-up

house robber step 2

lecture-34/house-robber.js
// step 2: calculation
function robStep2 (nums) {

  const dfs = (i) => {

    if(i >= nums.length) return 0

    return Math.max(
      nums[i] + dfs(i + 2), // house after adjacent
      dfs(i + 1) // adjacent house
    )
  }

  return dfs(0)
}
$ node house-robber.js
robStep2 [1,3,4]: 5

Step 3: cache distinct DFS calls

house robber step 3

lecture-34/house-robber.js
// step 3: cache
function robStep3 (nums) {

  const cache = {}

  const dfs = (i) => {

    if(i >= nums.length) return 0

    if(cache[i] != undefined) {
      return cache[i]
    } else {
      const profit = Math.max(
        nums[i] + dfs(i + 2), // house after adjacent
        dfs(i + 1) // adjacent house
      )
      cache[i] = profit
      return profit
    }
  }

  return dfs(0)
}

console.log('robStep1 [1,3,4]:', robStep1([1,3,4]))
console.log('robStep2 [1,3,4]:', robStep2([1,3,4])) // 5
console.log('robStep3 [1,3,4]:', robStep3([1,3,4])) // 5

console.time('no cache')
console.log(robStep2([183,219,57,193,94,233,202,154,65,240,97,234,100,249,186,66,90,238,168,128,177,235,50,81,185,165,217,207,88,80,112,78,135,62,228,247,211])) // 3365
console.timeEnd('no cache') // no cache: 663.464ms

console.time('cached')
console.log(robStep3([183,219,57,193,94,233,202,154,65,240,97,234,100,249,186,66,90,238,168,128,177,235,50,81,185,165,217,207,88,80,112,78,135,62,228,247,211])) // 3365
console.timeEnd('cached') // cached: 0.064ms
$ node house-robber.js
robStep3 [1,3,4]: 5
3365
no cache: 683.835ms
3365
cached: 0.064ms

Testing with Leetcode test cases

house robber lc test

Characteristics of problems can be solved by Sam's DP

Problem Input characteristics Algorithm Time
Complexity
Multi-stage decision making process (Dynamic Programming problems) - any (array, string, graph, ...) Sam's DP O(states created)

Let's connect and help the world to demystify Dynamic Programming

  • I'd love to hear your learning stories as well as how my DSA course can be improved to help you learn better. Come say hi on my Linkedin!
  • Dynamic Progamming is a myth with almost everyone right now. If you find this profoundly useful. Probably it'll be useful with a lot of people too. That so, let's help the world to demystify Dynamic Programming by share, like, subscribe and comment on the Youtube videos. It'll help to spread the video faster.

Real life interview questions

Type 1: a few choices

Type 2: n choices

Type 3: full data point combinations

More on Leetcode #dynamic-programming