1488. 避免洪水泛滥
算法掌握:
- hash表
- 链表
- 迭代器
- 模拟
解题思路:
本题是一个中等题对语法的熟练度比较高,难度就是一个脑筋急转弯的思维模拟题,下雨天的下标直接赋值 -1 即可,先将没有下雨的情况可以抽水的情况用链表存储起来,因为是顺序存储所有一定是升序,然后如果是下雨天,判断此池子是否已经被填充过了,如果填充过在之前那天开始到至今有没有可以抽取的机会,就与开始存储的链表进行比较即可,有就用掉抽取的机会,并刷新填充池子的时间,抽取机会从链表中删除,(为什么用链表而不是数组是因为,删除数组中一个值,要重新维护数组位置,效率比较慢),不能抽取则直接返回空数组即可
java code:
class Solution {
public int[] avoidFlood(int[] rains) {
int size = rains.length;
int[] ans = new int[size];
// 默认填充 1
Arrays.fill(ans, 1);
// 记录可以抽水的日期
List<Integer> pump = new LinkedList<>();
// 记录填充的日期
Map<Integer, Integer> rainsFill = new HashMap<>();
for(int i = 0; i < size; i++){
if(rains[i] == 0) pump.add(i);
else{
ans[i] = -1;
// 如何已经被填过了,判断是否可以抽取
if (rainsFill.containsKey(rains[i])) {
int start = rainsFill.get(rains[i]);
boolean isPump = false;
for (int j = 0; j < pump.size(); j++) {
if (pump.get(j) > start) {
ans[pump.get(j)] = rains[i];
pump.remove(j);
isPump = true;
break;
}
}
if (!isPump) return new int[0];
}
rainsFill.put(rains[i], i);
}
}
return ans;
}
}
c++ code:
class Solution {
public:
vector<int> avoidFlood(vector<int>& rains) {
int size = rains.size();
vector<int> ans(size, 1);
list<int> pump; // 记录可以抽水的日期
unordered_map<int, int> rains_fill; // 记录已被填满的池子所对应填满的日期
for(int i = 0; i < size; i++){
if(rains[i] == 0) pump.push_back(i);
else{
ans[i] = -1;
// 已经被填满了,判断是否在前几天可以抽取
if(rains_fill.find(rains[i]) != rains_fill.end()){
int start = rains_fill[rains[i]];
// 记录是否能被抽空,初始化不能
bool is_pump = false;
// 链表通过迭代器遍历
for(list<int>::iterator it = pump.begin(); it != pump.end(); it++){
if(*it > start){
ans[*it] = rains[i];
pump.erase(it);
is_pump = true;
break;
}
}
if(!is_pump) return {};
}
// 刷新填满时间
rains_fill[rains[i]] = i;
}
}
return ans;
}
};