[
dp
monotonic deque
greedy
stack
]
Leetcode 1130. Minimum Cost Tree From Leaf Values
Problem statement
https://leetcode.com/problems/minimum-cost-tree-from-leaf-values/
Solution 1
First solution is using dp with states dp(i, j)
is answer for arr[i: j + 1]
.
Complexity
It is O(n^3)
for time and O(n^2)
for space.
Code
class Solution:
def mctFromLeafValues(self, arr):
n = len(arr)
m = {(i, j): max(arr[i:j+1]) for i in range(n) for j in range(i, n)}
@lru_cache(None)
def dp(i, j):
if i == j: return arr[i]
return min(dp(i, k) + dp(k + 1, j) + m[i, k]*m[k+1, j] for k in range(i, j))
return dp(0, n - 1) - sum(arr)
Solution 2
In fact we can do better, using monotonic stack! The idea is that for each element arr[i]
we need to find the closest element to the left and closest element to the right which is >= arr[i]
. Then the answer will be sum of arr[i] * min(lft[i], rgh[i])
. However it is a good question, why, it is greedy idea, proof TBD. For this we can reuse problem Leetcode 0907 Sum of Subarray Minimums.
Complexity
It is O(n)
for time and space.
Code
class Solution:
def mctFromLeafValues(self, arr):
n = len(arr)
rgh, lft = [float("inf")]*n, [float("inf")]*n
stack1 = []
for i in range(n):
while stack1 and arr[i] >= arr[stack1[-1]]:
idx = stack1.pop()
rgh[idx] = arr[i]
stack1.append(i)
stack2 = []
for i in range(n-1, -1, -1):
while stack2 and arr[i] > arr[stack2[-1]]:
idx = stack2.pop()
lft[idx] = arr[i]
stack2.append(i)
ans = 0
for x, y, a in zip(lft, rgh, arr):
if min(x, y) != float("inf"): ans += min(x, y) * a
return ans