第一次尝试失败:尝试用数组 直接存rains里的值,通过后面再次遇到这个值大于1,则用前面的0来消除之前的一次洪水,但是只能通过案例,发现rains里的值最大可达1e9! 故数组失效。
第二次尝试失败:尝试用队列来写 同时二分搜索 但是队列 先进先出 的特性无法满足 要在 两个数之间去除值(两个数:某值第一次出现处 到 第二次出现处 )
下例为失败code:
class Solution {
public:
static const int N=1e5+10;
int find(vector<int> a, int st, int ed,int x)
{
int l = st - 1, r = ed + 1;
while (l + 1 < r)
{
int mid = l + r >> 1;
if (a[mid] >= x)
r = mid;
else
l = mid;
}
return r==ed+1?-1:r;
}
vector<int> avoidFlood(vector<int>& rains) {
int n=rains.size();
vector<int> ans(n,1);
vector<int> st(N);
int hh=-1,tt=0;
unordered_map<int,int> vis;
for(int i=0;i<n;i++){
if(rains[i]==0){
st[++hh]=i;
}
else{
ans[i]=-1;
if(vis.count(rains[i])){
int l=find(st,tt,hh,vis[rains[i]]);
if(l==-1) return{};
ans[st[l]]=rains[i];
tt++;
}
vis[rains[i]]=i;
}
}
return ans;
}
};
get:set的基本性质【总结】C++ 基础数据结构 —— STL之集合(set)用法详解_c++ stl set-优快云博客
set基本性质
1.logN的时间 增删查改
2.注意插入元素不可相同
3.元素自动排序(默认从小到大)
4.不支持下标操作
5.不能更改里面的值
set<int> st;
st.insert();
st.count();
st.lower_bound(); st.upper_bound();//注意得到结果为 定位器(即地址)
st.erase();//注意 填写为 定位器(即地址)
st.empty();
大概思路:二分—>利用set的特性 可以方便二分查找 反复出现的rains[i] 第一次出现时 第一个零出现位置 然后把该位置的ans设为rains[i]
每次插入 分两种情况:
情况一:rains[i]==0
插入st中 保证后面需要的时候可以用 注意插入时 st{[0]=i(第一个0下标),[1]=(第二个0下标)}
若一次erase 后变成st{[0]=(二个0下标)}
情况二:rains[i]!=0
1.存储结果
2.若是第二次出现:
1.找到在st中 比第一次出现的下标 大于等于的值 (若不为最后 说明st中有值 既前面有0可以 泄水)
2.让ans下标这个值 标注 清除st一次
3.记录rains[i] 下标
AC code:
class Solution {
public:
vector<int> avoidFlood(vector<int>& rains) {
int n=rains.size();
vector<int> ans(n,1);
set<int> st;
unordered_map<int,int> vis;
for(int i=0;i<n;i++){
if(rains[i]==0){
st.insert(i);
}else{
ans[i]=-1;
if(vis.count(rains[i])){
auto l=st.lower_bound(vis[rains[i]]);
if(l==st.end()){
return {};
}
ans[*l]=rains[i];
st.erase(l);
}
vis[rains[i]]=i;
}
}
return ans;
}
};