每日一题 2023.10.13

1488. 避免洪水泛滥 - 力扣(LeetCode)

第一次尝试失败:尝试用数组 直接存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;
    }
};

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值