Medium
题目描述
给你一个下标从 0 开始的字符串 hamsters ,其中 hamsters[i] 是:
'H'表示第i个位置有一只仓鼠'.'表示第i个位置是空的
你需要在一些空位置放置食物桶来喂养仓鼠。如果仓鼠的左边或右边至少有一个食物桶,那么这只仓鼠就能被喂养。更正式地说,位置 i 的仓鼠能被喂养,当且仅当你在位置 i - 1 和/或位置 i + 1 放置了食物桶。
返回你需要放置在空位置的食物桶的 最少 数量,以便喂养所有仓鼠,如果无法喂养所有仓鼠则返回 -1。
示例 1:
输入: hamsters = "H..H"
输出: 2
解释: 我们在位置 1 和 2 放置两个食物桶。
可以证明如果只放一个食物桶,其中一只仓鼠无法被喂养。
示例 2:
输入: hamsters = ".H.H."
输出: 1
解释: 我们在位置 2 放置一个食物桶。
示例 3:
输入: hamsters = ".HHH."
输出: -1
解释: 如果我们在所有空位置都放置食物桶,位置 2 的仓鼠仍然无法吃到食物。
提示:
1 <= hamsters.length <= 10^5hamsters[i]要么是'H'要么是'.'
解题思路
这道题的核心思路是贪心算法。我们需要找到用最少食物桶喂养所有仓鼠的策略。
关键观察:
- 如果存在连续的三只仓鼠(“HHH”),那么中间的仓鼠无法被喂养,直接返回 -1
- 对于每只仓鼠,我们有两个选择:在它左边放桶或右边放桶
- 贪心策略:优先在仓鼠右边放桶,因为这样可能同时喂养下一只仓鼠
解法思路:
- 预处理检查:先检查是否存在不可能的情况(连续三只仓鼠)
- 贪心放置:从左到右遍历,遇到仓鼠时:
- 如果左边已有桶,跳过
- 否则尽量在右边放桶(更优选择)
- 如果右边不能放,只能在左边放
这个贪心策略的正确性在于:在右边放桶不仅能喂养当前仓鼠,还可能喂养下一只仓鼠,从而减少总桶数。
时间复杂度 O(n),空间复杂度 O(1),是最优解法。
代码实现
class Solution {
public:
int minimumBuckets(string hamsters) {
int n = hamsters.length();
int buckets = 0;
for (int i = 0; i < n; i++) {
if (hamsters[i] == 'H') {
// 检查左边是否已经有桶
if (i > 0 && hamsters[i-1] == 'B') {
continue;
}
// 尝试在右边放桶
if (i + 1 < n && hamsters[i+1] == '.') {
hamsters[i+1] = 'B';
buckets++;
}
// 否则在左边放桶
else if (i > 0 && hamsters[i-1] == '.') {
hamsters[i-1] = 'B';
buckets++;
}
// 无法放桶,返回-1
else {
return -1;
}
}
}
return buckets;
}
};
class Solution:
def minimumBuckets(self, hamsters: str) -> int:
hamsters = list(hamsters)
n = len(hamsters)
buckets = 0
for i in range(n):
if hamsters[i] == 'H':
# 检查左边是否已经有桶
if i > 0 and hamsters[i-1] == 'B':
continue
# 尝试在右边放桶
if i + 1 < n and hamsters[i+1] == '.':
hamsters[i+1] = 'B'
buckets += 1
# 否则在左边放桶
elif i > 0 and hamsters[i-1] == '.':
hamsters[i-1] = 'B'
buckets += 1
# 无法放桶,返回-1
else:
return -1
return buckets
public class Solution {
public int MinimumBuckets(string hamsters) {
char[] arr = hamsters.ToCharArray();
int n = arr.Length;
int buckets = 0;
for (int i = 0; i < n; i++) {
if (arr[i] == 'H') {
// 检查左边是否已经有桶
if (i > 0 && arr[i-1] == 'B') {
continue;
}
// 尝试在右边放桶
if (i + 1 < n && arr[i+1] == '.') {
arr[i+1] = 'B';
buckets++;
}
// 否则在左边放桶
else if (i > 0 && arr[i-1] == '.') {
arr[i-1] = 'B';
buckets++;
}
// 无法放桶,返回-1
else {
return -1;
}
}
}
return buckets;
}
}
/**
* @param {string} hamsters
* @return {number}
*/
var minimumBuckets = function(hamsters) {
let arr = hamsters.split('');
let n = arr.length;
let buckets = 0;
for (let i = 0; i < n; i++) {
if (arr[i]
复杂度分析
| 复杂度类型 | 分析 |
|---|---|
| 时间复杂度 | O(n) - 只需要遍历字符串一次 |
| 空间复杂度 | O(n) - 需要复制字符串用于修改(某些语言中字符串不可变) |