887 - Hard - Super Egg Drop
About 1 min
887 - Hard - Super Egg Drop
dp(K, N)
: The minimum number of steps of f
Base case:
K = 1
, we need to start from the first floor to the N-th floor, hencef
isN
;N = 1
,f
is always 1;N = 0
, we’ve already found the floor sof
is 0.
At this point, drop the egg on the floor x
. The state could then be transferred to:
- The egg is broken:
dp(K - 1, x)
; - The egg is not broken:
dp(K, N - x)
.
dp(K, N) = 1 + Max(dp(K - 1, x), dp(K - 1, N - x))
We need to find the x
that makes the value smallest.
dp(K - 1, x)
is increasing on x
dp(K - 1, N - x)
is decreasing on x
We can binary search to find the x
:
- If
dp(K - 1, x)
>dp(K - 1, N - x)
: thex
is too big; - If
dp(K - 1, x)
<dp(K - 1, N - x)
: thex
is too small.
x
should be an interger, so we need to check both the lower and higer bounds to find the smaller value.
TypeScript solution:
function superEggDrop(k: number, n: number): number {
const dp = Array.from({ length: k + 1 }, () => Array.from<number>({ length: n + 1 }).fill(-1))
for (let i = 1; i <= n; i++) {
// k === 1
dp[1][i] = i
}
for (let i = 1; i <= k; i++) {
// n === 0
dp[i][0] = 0
// n === 1
dp[i][1] = 1
}
return _find(k, n)
function _find(_k: number, _n: number): number {
if (dp[_k][_n] >= 0) {
return dp[_k][_n]
}
let low = 1
let high = _n
while (low + 1 < high) {
const x = Math.floor((low + high) / 2)
// broken
const f1 = _find(_k - 1, x - 1)
// not broken
const f2 = _find(_k, _n - x)
if (f1 < f2) {
low = x
} else if (f1 > f2) {
high = x
} else {
low = x
high = x
}
}
dp[_k][_n] = 1 + Math.min(
Math.max(
_find(_k - 1, low - 1),
_find(_k, _n - low)
),
Math.max(
_find(_k - 1, high - 1),
_find(_k, _n - high)
),
)
return dp[_k][_n]
}
}