自己的思路:贪心
class Solution {
public:
int minimumBuckets(string street) {
int n = street.size();
int i = 0, ans = 0;
int flag = false; //false表示没有桶
while (i < n) {
if (street[i] == '.' && i - 1 >= 0 && street[i - 1] == '.') flag = false; //这种需要把flag状态恢复!!!
if (street[i] == '.') ++i;
else { //墙
if (!flag) { //左边没有桶
if (i + 1 >= n || street[i + 1] == 'H') { //右边是H或者越界
if (i - 1 < 0) return -1;
else if (street[i - 1] != 'H') { //桶放到左边
ans++;
i++;
}else {
return -1;
}
}else { //右边不是H 桶放到右边
flag = true;
ans++;
i++;
}
}else { //左边有桶
i++;
flag = false; //需要把flag状态恢复!!!
}
}
}
return ans;
}
};
上面存在的问题:
1:flag的状态需要一直维护,很容易出错
2:代码风格不好。
针对性优化:
1:定义一个变量last来存上一个桶放的位置。
2:if …else if …else if …else 来优化(见上面纸)
class Solution {
public:
int minimumBuckets(string street) {
int ans = 0, n = street.size();
int i = 0, last = -2; //last存上一个桶的位置
while (i < n) {
if (street[i] == 'H') {
if (last == i - 1) ++i;
else if (i + 1 < n && street[i + 1] == '.') {
ans++;
last = i + 1;
++i;
}else if (i - 1 >= 0 && street[i - 1] == '.') {
ans++;
last = i - 1;
++i;
}else return -1;
}else {
++i;
}
}
return ans;
}
};
另外一种思路:
依旧是贪心,利用了H.H中间一定有桶这个原理
1:存在三个H的情况,“HHH”,则说明不能放一个桶接水,直接返回-1
2:字符串的开头或者结果存在两个H的情况,“HH”,说明也不能放一个桶接水,同样返回-1
3:字符串长度为1且字符串为"H"的情况,直接返回-1
先统计出有多少个房屋,再统计出有多少个位置可以同时接左右两个房屋的水,然后减去即可。("H.H"这种情况可以同时接两个房屋的水)
class Solution {
public:
int minimumBuckets(string street) {
int n = street.size();
if (n == 1 && street[0] == 'H') return -1;
if (n >= 2 && street[0] == 'H' && street[1] == 'H') return -1;
if (n >= 2 && street[n - 1] == 'H' && street[n - 2] == 'H') return -1;
if (street.find("HHH") != -1) return -1;
int nums1 = count(street.begin(), street.end(), 'H');
int nums2 = 0;
for (int i = 0; i < n; ++i) {
if (i + 2 < n && street.substr(i, 3) == "H.H") {
nums2++;
i += 2; //不是i+=3,因为for后面还有一个++i,相当于i向后移动了3个位置
}
}
return nums1 - nums2;
}
};
易错点:
1.计算的是,"H.H"的个数,计算出一个后,要跳过这三个下标!!!
2.不是i+=3,因为for后面还有一个++i !!!