A fence is made of n adjacent vertical boards. Board i has width 1 and height heights[i].
You have a brush of width 1 and may perform only these two types of painting operations:
- Vertical stroke: paint one entire board from bottom to top in a single operation.
- Horizontal stroke: paint exactly one unit of height across a contiguous segment of adjacent boards. A horizontal stroke may cover only portions of boards that still need paint.
Return the minimum number of operations required to paint the entire fence.
Function Description
Complete the function
minPaintOperationsin the editor below.minPaintOperationshas the following parameter: int[] heights: the heights of the boards Returnsint: the minimum number of painting operations.
Constraints
The source thread did not provide explicit numeric bounds.
heights.length ≥ 1- Each
heights[i]is a non-negative integer.
解法
分治/贪心。对当前区间 [l, r],最优策略是要么垂直涂每根 (r-l+1 次);要么先横涂 min(heights[l..r]) 次,再对水平线之上的剩余部分递归处理被切分的子区间。取两者最小值。时间复杂度 O(n²) 最坏(顺序栈大小),可优化为 O(n) 用稀疏表,但 n 较小直接递归即可。空间复杂度 O(n) 递归栈。
from typing import List
def minPaintOperations(heights: List[int]) -> int:
def solve(l: int, r: int, base: int) -> int:
if l > r:
return 0
m = min(heights[l:r + 1])
# vertical
vertical = r - l + 1
# horizontal: paint (m - base) horizontal strokes, then recurse on sub-intervals
horizontal = m - base
i = l
while i <= r:
if heights[i] == m:
i += 1
continue
j = i
while j <= r and heights[j] > m:
j += 1
horizontal += solve(i, j - 1, m)
i = j
return min(vertical, horizontal)
return solve(0, len(heights) - 1, 0)class Solution {
int[] h;
int minPaintOperations(int[] heights) {
this.h = heights;
return solve(0, heights.length - 1, 0);
}
private int solve(int l, int r, int base) {
if (l > r) return 0;
int m = Integer.MAX_VALUE;
for (int i = l; i <= r; i++) m = Math.min(m, h[i]);
int vertical = r - l + 1;
int horizontal = m - base;
int i = l;
while (i <= r) {
if (h[i] == m) { i++; continue; }
int j = i;
while (j <= r && h[j] > m) j++;
horizontal += solve(i, j - 1, m);
i = j;
}
return Math.min(vertical, horizontal);
}
}class Solution {
public:
int minPaintOperations(vector<int>& heights) {
return solve(heights, 0, (int)heights.size() - 1, 0);
}
private:
int solve(vector<int>& h, int l, int r, int base) {
if (l > r) return 0;
int m = INT_MAX;
for (int i = l; i <= r; i++) m = min(m, h[i]);
int vertical = r - l + 1;
int horizontal = m - base;
int i = l;
while (i <= r) {
if (h[i] == m) { i++; continue; }
int j = i;
while (j <= r && h[j] > m) j++;
horizontal += solve(h, i, j - 1, m);
i = j;
}
return min(vertical, horizontal);
}
};