Bird
Raised Fist0
Interview Prepdp-grid-intervalshardAmazonGoogle

Dungeon Game

Choose your preparation mode4 modes available
📋
Problem

Imagine a knight trapped in a dungeon filled with monsters and magic potions, needing to find the minimum initial health to survive the journey to rescue the princess.

You are given an m x n grid dungeon where each cell contains an integer representing health points gained (positive) or lost (negative). The knight starts at the top-left cell and must reach the bottom-right cell by moving only right or down. The knight's health must never drop to zero or below at any point. Determine the minimum initial health the knight needs to start with to reach the princess safely.

1 ≤ m, n ≤ 200-1000 ≤ dungeon[i][j] ≤ 1000
Edge cases: Single cell with positive value → minimum initial health is 1Single cell with negative value → minimum initial health is 1 - cell valueAll cells zero → minimum initial health is 1
</>
IDE
def calculateMinimumHP(dungeon: List[List[int]]) -> int:public int calculateMinimumHP(int[][] dungeon)int calculateMinimumHP(vector<vector<int>>& dungeon)function calculateMinimumHP(dungeon)
def calculateMinimumHP(dungeon):
    # Write your solution here
    pass
class Solution {
    public int calculateMinimumHP(int[][] dungeon) {
        // Write your solution here
        return 0;
    }
}
#include <vector>
using namespace std;

int calculateMinimumHP(vector<vector<int>>& dungeon) {
    // Write your solution here
    return 0;
}
function calculateMinimumHP(dungeon) {
    // Write your solution here
}
Coming soon
0/9
Common Bugs to Avoid
Wrong: 0Not clamping minimum health to 1, allowing zero or negative health.✅ Use max(1, calculated_health) at every DP step to ensure health never drops below 1.
Wrong: Incorrect low values (e.g., 3 instead of 7)Using greedy approach picking only one path (right or down) instead of minimum of both.✅ At each cell, take min of dp[i+1][j] and dp[i][j+1] to consider all paths.
Wrong: Too high values (e.g., 10 instead of 7)Not taking minimum of next steps, or adding dungeon[i][j] instead of subtracting.✅ Use dp[i][j] = max(1, min(dp[i+1][j], dp[i][j+1]) - dungeon[i][j]) correctly.
Wrong: Timeout or no outputUsing brute force recursion without memoization or DP.✅ Implement DP with memoization or bottom-up tabulation to achieve O(m*n) time.
✓
Test Cases
t1_01basic
Input{"dungeon":[[-2,-3,3],[-5,-10,1],[10,30,-5]]}
Expected7

Starting with 7 health, the knight can survive the path (right, right, down, down) without health dropping below 1.

t1_02basic
Input{"dungeon":[[0,-3],[-10,0]]}
Expected4

Minimum initial health 4 allows path (right, down) without health dropping below 1.

t2_01edge
Input{"dungeon":[[5]]}
Expected1

Single positive cell requires minimum initial health 1.

t2_02edge
Input{"dungeon":[[-7]]}
Expected8

Single negative cell requires initial health 1 - (-7) = 8.

t2_03edge
Input{"dungeon":[[0,0],[0,0]]}
Expected1

All zero cells require minimum initial health 1.

t3_01corner
Input{"dungeon":[[-2,-3,3],[-5,-10,1],[10,30,-50]]}
Expected52

Large negative value at bottom-right requires high initial health to survive.

t3_02corner
Input{"dungeon":[[-2,-3,3],[-5,-10,1],[10,30,-5],[0,0,-1]]}
Expected7

Extra row with zeros and a small negative at end does not reduce initial health below 7.

t3_03corner
Input{"dungeon":[[-1,-1],[-1,-1]]}
Expected3

Uniform negative values require initial health 3 to survive any path.

t4_01performance
Input{"dungeon":[[-1000,-999,-998,-997,-996,-995,-994,-993,-992,-991,-990,-989,-988,-987,-986,-985,-984,-983,-982,-981],[-980,-979,-978,-977,-976,-975,-974,-973,-972,-971,-970,-969,-968,-967,-966,-965,-964,-963,-962,-961],[-960,-959,-958,-957,-956,-955,-954,-953,-952,-951,-950,-949,-948,-947,-946,-945,-944,-943,-942,-941],[-940,-939,-938,-937,-936,-935,-934,-933,-932,-931,-930,-929,-928,-927,-926,-925,-924,-923,-922,-921],[-920,-919,-918,-917,-916,-915,-914,-913,-912,-911,-910,-909,-908,-907,-906,-905,-904,-903,-902,-901],[-900,-899,-898,-897,-896,-895,-894,-893,-892,-891,-890,-889,-888,-887,-886,-885,-884,-883,-882,-881],[-880,-879,-878,-877,-876,-875,-874,-873,-872,-871,-870,-869,-868,-867,-866,-865,-864,-863,-862,-861],[-860,-859,-858,-857,-856,-855,-854,-853,-852,-851,-850,-849,-848,-847,-846,-845,-844,-843,-842,-841],[-840,-839,-838,-837,-836,-835,-834,-833,-832,-831,-830,-829,-828,-827,-826,-825,-824,-823,-822,-821],[-820,-819,-818,-817,-816,-815,-814,-813,-812,-811,-810,-809,-808,-807,-806,-805,-804,-803,-802,-801],[-800,-799,-798,-797,-796,-795,-794,-793,-792,-791,-790,-789,-788,-787,-786,-785,-784,-783,-782,-781],[-780,-779,-778,-777,-776,-775,-774,-773,-772,-771,-770,-769,-768,-767,-766,-765,-764,-763,-762,-761],[-760,-759,-758,-757,-756,-755,-754,-753,-752,-751,-750,-749,-748,-747,-746,-745,-744,-743,-742,-741],[-740,-739,-738,-737,-736,-735,-734,-733,-732,-731,-730,-729,-728,-727,-726,-725,-724,-723,-722,-721],[-720,-719,-718,-717,-716,-715,-714,-713,-712,-711,-710,-709,-708,-707,-706,-705,-704,-703,-702,-701],[-700,-699,-698,-697,-696,-695,-694,-693,-692,-691,-690,-689,-688,-687,-686,-685,-684,-683,-682,-681],[-680,-679,-678,-677,-676,-675,-674,-673,-672,-671,-670,-669,-668,-667,-666,-665,-664,-663,-662,-661],[-660,-659,-658,-657,-656,-655,-654,-653,-652,-651,-650,-649,-648,-647,-646,-645,-644,-643,-642,-641],[-640,-639,-638,-637,-636,-635,-634,-633,-632,-631,-630,-629,-628,-627,-626,-625,-624,-623,-622,-621],[-620,-619,-618,-617,-616,-615,-614,-613,-612,-611,-610,-609,-608,-607,-606,-605,-604,-603,-602,-601]]}
⏱ Performance - must finish in 2000ms

Large 20x20 grid with large negative values to test O(m*n) DP performance within 2 seconds.

Practice

(1/5)
1. You need to find the cheapest cost to travel from a source city to a destination city with at most K stops, given a list of flights with costs. Which algorithmic approach guarantees finding the optimal solution efficiently under these constraints?
easy
A. Greedy algorithm using Dijkstra's shortest path without modification
B. Topological sort followed by single pass relaxation of edges
C. Simple depth-first search exploring all paths without pruning
D. Dynamic programming using a bottom-up approach iterating over stops

Solution

  1. Step 1: Understand the problem constraints

    The problem requires finding the cheapest flight with at most K stops, which limits path length and requires considering multiple paths.
  2. Step 2: Identify suitable algorithm

    Greedy Dijkstra fails because it doesn't limit stops; DFS is exponential; topological sort requires DAG which flights graph may not be. Bottom-up DP iterates over stops and relaxes edges, guaranteeing optimal cost within K stops.
  3. Final Answer:

    Option D -> Option D
  4. Quick Check:

    Bottom-up DP with stops limit ensures optimal solution [OK]
Hint: DP with stops limit ensures optimal cost [OK]
Common Mistakes:
  • Using Dijkstra without stop limit
  • Trying DFS without pruning
  • Assuming DAG for topological sort
2. You are given a grid of non-negative integers representing costs. Starting from the top-left corner, you want to reach the bottom-right corner by moving only down or right, minimizing the total cost along the path. Which algorithmic approach guarantees finding the minimum total cost efficiently?
easy
A. A greedy algorithm that always moves to the adjacent cell with the smallest cost
B. Dynamic programming that builds up solutions from smaller subproblems using a grid-based state
C. Pure brute force recursion exploring all possible paths without memoization
D. Divide and conquer by splitting the grid into halves and solving independently

Solution

  1. Step 1: Understand problem constraints

    The problem requires minimizing path cost with only down or right moves, which naturally forms overlapping subproblems.
  2. Step 2: Identify suitable algorithmic pattern

    Dynamic programming efficiently solves overlapping subproblems by storing intermediate results, unlike greedy which can fail on some grids, brute force which is exponential, or divide and conquer which doesn't handle dependencies well.
  3. Final Answer:

    Option B -> Option B
  4. Quick Check:

    DP uses subproblem solutions to build the answer bottom-up [OK]
Hint: DP handles overlapping subproblems and optimal substructure [OK]
Common Mistakes:
  • Assuming greedy always works for grid path problems
  • Thinking brute force is efficient enough
  • Believing divide and conquer applies without overlapping subproblems
3. Consider the following bottom-up DP code for the Strange Printer problem. What is the final returned value when the input string is "aba"?
easy
A. 3
B. 4
C. 1
D. 2

Solution

  1. Step 1: Compress input string "aba"

    Compression does not change string since no consecutive duplicates: s = "aba", n=3.
  2. Step 2: Trace dp table filling

    Base cases: dp[0][0]=1, dp[1][1]=1, dp[2][2]=1. For length=2: - dp[0][1]: dp[0][0]+1=2, s[0]!=s[1], so dp[0][1]=2 - dp[1][2]: dp[1][1]+1=2, s[1]!=s[2], so dp[1][2]=2 For length=3: - dp[0][2]: dp[0][1]+1=3 Check k=0: s[0]==s[2] ('a'=='a'), dp[0][0]+dp[1][1]=1+1=2 < 3, so dp[0][2]=2
  3. Final Answer:

    Option D -> Option D
  4. Quick Check:

    Output matches known minimal turns for "aba" [OK]
Hint: Check dp merging when s[k] == s[j] reduces turns [OK]
Common Mistakes:
  • Forgetting to merge intervals when characters match
4. You are given a string representing a sequence of colored balls on a board and a multiset of balls in hand. Your goal is to clear the board by inserting balls from your hand such that any group of three or more consecutive balls of the same color is removed, possibly triggering chain reactions. Which algorithmic approach guarantees finding the minimum number of insertions needed to clear the board optimally?
easy
A. Interval dynamic programming with memoization exploiting optimal substructure
B. Topological sorting of ball groups followed by greedy removals
C. Pure brute force recursion without memoization exploring all insertions
D. Greedy insertion of balls at the earliest possible position to remove groups

Solution

  1. Step 1: Understand problem structure

    The problem requires minimizing insertions to clear the board, which involves exploring overlapping subproblems and optimal substructure.
  2. Step 2: Identify suitable algorithm

    Interval DP with memoization efficiently explores all intervals and hand states, guaranteeing minimal moves by considering all splits and removals.
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    Interval DP is known for solving interval removal problems optimally [OK]
Hint: Interval DP handles overlapping subproblems optimally [OK]
Common Mistakes:
  • Assuming greedy insertion always yields minimal moves
  • Using brute force without memoization leads to exponential time
  • Misapplying topological sort which is unrelated here
5. What is the time complexity of the bottom-up DP solution for the Strange Printer problem after string compression, where m is the length of the compressed string?
medium
A. O(m^2)
B. O(m^3)
C. O(n^3) where n is original string length
D. O(m^2 * log m)

Solution

  1. Step 1: Identify loops in bottom-up DP

    There are three nested loops: length (1 to m), start index i (up to m), and partition index k (between i and j), each up to m.
  2. Step 2: Calculate complexity

    Overall complexity is O(m * m * m) = O(m^3). Compression reduces n to m, so complexity depends on compressed length.
  3. Final Answer:

    Option B -> Option B
  4. Quick Check:

    Three nested loops over compressed length m [OK]
Hint: Three nested loops over compressed string length cause cubic time [OK]
Common Mistakes:
  • Confusing original length n with compressed length m
  • Forgetting the inner loop over k
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard