|
| 1 | +# [3119. Maximum Number of Potholes That Can Be Fixed](https://leetcode.cn/problems/maximum-number-of-potholes-that-can-be-fixed) |
| 2 | + |
| 3 | +[English Version](/solution/3100-3199/3119.Maximum%20Number%20of%20Potholes%20That%20Can%20Be%20Fixed/README_EN.md) |
| 4 | + |
| 5 | +<!-- tags: --> |
| 6 | + |
| 7 | +## 题目描述 |
| 8 | + |
| 9 | +<!-- 这里写题目描述 --> |
| 10 | + |
| 11 | +<p>You are given a string <code>road</code>, consisting only of characters <code>"x"</code> and <code>"."</code>, where each <code>"x"</code> denotes a <em>pothole</em> and each <code>"."</code> denotes a smooth road, and an integer <code>budget</code>.</p> |
| 12 | + |
| 13 | +<p>In one repair operation, you can repair <code>n</code> <strong>consecutive</strong> potholes for a price of <code>n + 1</code>.</p> |
| 14 | + |
| 15 | +<p>Return the <strong>maximum</strong> number of potholes that can be fixed such that the sum of the prices of all of the fixes <strong>doesn't go over</strong> the given budget.</p> |
| 16 | + |
| 17 | +<p> </p> |
| 18 | +<p><strong class="example">Example 1:</strong></p> |
| 19 | + |
| 20 | +<div class="example-block"> |
| 21 | +<p><strong>Input:</strong> <span class="example-io">road = "..", budget = 5</span></p> |
| 22 | + |
| 23 | +<p><strong>Output:</strong> <span class="example-io">0</span></p> |
| 24 | + |
| 25 | +<p><strong>Explanation:</strong></p> |
| 26 | + |
| 27 | +<p>There are no potholes to be fixed.</p> |
| 28 | +</div> |
| 29 | + |
| 30 | +<p><strong class="example">Example 2:</strong></p> |
| 31 | + |
| 32 | +<div class="example-block"> |
| 33 | +<p><strong>Input:</strong> <span class="example-io">road = "..xxxxx", budget = 4</span></p> |
| 34 | + |
| 35 | +<p><strong>Output:</strong> <span class="example-io">3</span></p> |
| 36 | + |
| 37 | +<p><strong>Explanation:</strong></p> |
| 38 | + |
| 39 | +<p>We fix the first three potholes (they are consecutive). The budget needed for this task is <code>3 + 1 = 4</code>.</p> |
| 40 | +</div> |
| 41 | + |
| 42 | +<p><strong class="example">Example 3:</strong></p> |
| 43 | + |
| 44 | +<div class="example-block"> |
| 45 | +<p><strong>Input:</strong> <span class="example-io">road = "x.x.xxx...x", budget = 14</span></p> |
| 46 | + |
| 47 | +<p><strong>Output:</strong> <span class="example-io">6</span></p> |
| 48 | + |
| 49 | +<p><strong>Explanation:</strong></p> |
| 50 | + |
| 51 | +<p>We can fix all the potholes. The total cost would be <code>(1 + 1) + (1 + 1) + (3 + 1) + (1 + 1) = 10</code> which is within our budget of 14.</p> |
| 52 | +</div> |
| 53 | + |
| 54 | +<p> </p> |
| 55 | +<p><strong>Constraints:</strong></p> |
| 56 | + |
| 57 | +<ul> |
| 58 | + <li><code>1 <= road.length <= 10<sup>5</sup></code></li> |
| 59 | + <li><code>1 <= budget <= 10<sup>5</sup> + 1</code></li> |
| 60 | + <li><code>road</code> consists only of characters <code>'.'</code> and <code>'x'</code>.</li> |
| 61 | +</ul> |
| 62 | + |
| 63 | +## 解法 |
| 64 | + |
| 65 | +### 方法一:计数 + 贪心 |
| 66 | + |
| 67 | +我们首先统计出每个连续的坑洼的数量,记录在数组 $cnt$ 中,即 $cnt[k]$ 表示有 $cnt[k]$ 个长度为 $k$ 的连续坑洼。 |
| 68 | + |
| 69 | +由于我们要尽可能多地修补坑洼,而对于长度为 $k$ 的连续坑洼,我们需要花费 $k + 1$ 的代价,应该优先修补长度较长的坑洼,这样可以使得代价最小。 |
| 70 | + |
| 71 | +因此,我们从最长的坑洼开始修补,对于长度为 $k$ 的坑洼,我们最多可以修补的个数为 $t = \min(\text{budget} / (k + 1), \text{cnt}[k])$,我们将修补的个数乘以长度 $k$ 加到答案中,然后更新剩余的预算。对于长度为 $k$ 的其余 $cnt[k] - t$ 个坑洼,我们将它们合并到长度为 $k - 1$ 的坑洼中。继续这个过程,直到遍历完所有的坑洼。 |
| 72 | + |
| 73 | +时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为字符串 $road$ 的长度。 |
| 74 | + |
| 75 | +<!-- tabs:start --> |
| 76 | + |
| 77 | +```python |
| 78 | +class Solution: |
| 79 | + def maxPotholes(self, road: str, budget: int) -> int: |
| 80 | + road += "." |
| 81 | + n = len(road) |
| 82 | + cnt = [0] * n |
| 83 | + k = 0 |
| 84 | + for c in road: |
| 85 | + if c == "x": |
| 86 | + k += 1 |
| 87 | + elif k: |
| 88 | + cnt[k] += 1 |
| 89 | + k = 0 |
| 90 | + ans = 0 |
| 91 | + for k in range(n - 1, 0, -1): |
| 92 | + t = min(budget // (k + 1), cnt[k]) |
| 93 | + ans += t * k |
| 94 | + budget -= t * (k + 1) |
| 95 | + cnt[k - 1] += cnt[k] - t |
| 96 | + return ans |
| 97 | +``` |
| 98 | + |
| 99 | +```java |
| 100 | +class Solution { |
| 101 | + public int maxPotholes(String road, int budget) { |
| 102 | + road += "."; |
| 103 | + int n = road.length(); |
| 104 | + int[] cnt = new int[n]; |
| 105 | + int k = 0; |
| 106 | + for (char c : road.toCharArray()) { |
| 107 | + if (c == 'x') { |
| 108 | + ++k; |
| 109 | + } else if (k > 0) { |
| 110 | + ++cnt[k]; |
| 111 | + k = 0; |
| 112 | + } |
| 113 | + } |
| 114 | + int ans = 0; |
| 115 | + for (k = n - 1; k > 0; --k) { |
| 116 | + int t = Math.min(budget / (k + 1), cnt[k]); |
| 117 | + ans += t * k; |
| 118 | + budget -= t * (k + 1); |
| 119 | + cnt[k - 1] += cnt[k] - t; |
| 120 | + } |
| 121 | + return ans; |
| 122 | + } |
| 123 | +} |
| 124 | +``` |
| 125 | + |
| 126 | +```cpp |
| 127 | +class Solution { |
| 128 | +public: |
| 129 | + int maxPotholes(string road, int budget) { |
| 130 | + road.push_back('.'); |
| 131 | + int n = road.size(); |
| 132 | + vector<int> cnt(n); |
| 133 | + int k = 0; |
| 134 | + for (char& c : road) { |
| 135 | + if (c == 'x') { |
| 136 | + ++k; |
| 137 | + } else if (k) { |
| 138 | + ++cnt[k]; |
| 139 | + k = 0; |
| 140 | + } |
| 141 | + } |
| 142 | + int ans = 0; |
| 143 | + for (k = n - 1; k; --k) { |
| 144 | + int t = min(budget / (k + 1), cnt[k]); |
| 145 | + ans += t * k; |
| 146 | + budget -= t * (k + 1); |
| 147 | + cnt[k - 1] += cnt[k] - t; |
| 148 | + } |
| 149 | + return ans; |
| 150 | + } |
| 151 | +}; |
| 152 | +``` |
| 153 | +
|
| 154 | +```go |
| 155 | +func maxPotholes(road string, budget int) (ans int) { |
| 156 | + road += "." |
| 157 | + n := len(road) |
| 158 | + cnt := make([]int, n) |
| 159 | + k := 0 |
| 160 | + for _, c := range road { |
| 161 | + if c == 'x' { |
| 162 | + k++ |
| 163 | + } else if k > 0 { |
| 164 | + cnt[k]++ |
| 165 | + k = 0 |
| 166 | + } |
| 167 | + } |
| 168 | + for k = n - 1; k > 0; k-- { |
| 169 | + t := min(budget/(k+1), cnt[k]) |
| 170 | + ans += t * k |
| 171 | + budget -= t * (k + 1) |
| 172 | + cnt[k-1] += cnt[k] - t |
| 173 | + } |
| 174 | + return |
| 175 | +} |
| 176 | +``` |
| 177 | + |
| 178 | +```ts |
| 179 | +function maxPotholes(road: string, budget: number): number { |
| 180 | + road += '.'; |
| 181 | + const n = road.length; |
| 182 | + const cnt: number[] = Array(n).fill(0); |
| 183 | + let k = 0; |
| 184 | + for (const c of road) { |
| 185 | + if (c === 'x') { |
| 186 | + ++k; |
| 187 | + } else if (k) { |
| 188 | + ++cnt[k]; |
| 189 | + k = 0; |
| 190 | + } |
| 191 | + } |
| 192 | + let ans = 0; |
| 193 | + for (k = n - 1; k; --k) { |
| 194 | + const t = Math.min(Math.floor(budget / (k + 1)), cnt[k]); |
| 195 | + ans += t * k; |
| 196 | + budget -= t * (k + 1); |
| 197 | + cnt[k - 1] += cnt[k] - t; |
| 198 | + } |
| 199 | + return ans; |
| 200 | +} |
| 201 | +``` |
| 202 | + |
| 203 | +<!-- tabs:end --> |
| 204 | + |
| 205 | +<!-- end --> |
0 commit comments