力扣周赛第二题,下午更新后两道

本题中其实看着条件很多,但是仔细读一下会发现,前四个条件都是固定条件。然后我们再看题。 我们的暴力做法是遍历a数组的字符串a的下标起始下标,然后遍历b数组的字符串b的下标起始下标,进行判断,但是这样会超时,所以我们是不是可以优化查找b数组,那么我们这里就发现到了一个第五个条件-k <= j - i <=k,i - k>=j,j <= k + i,那么我们有了已知的i和k,那么可以根据绝对值的数学性质找到j,那么我们怎么找最快呢,可以将b数组的下标加入到set中,然后通过lower_bound和upper_bound去寻找j,如果有,先判断该a数组下标是否添加过,如果添加过那就跳过,没有添加过就加入到res数组中。

class Solution {
public:
    //1.i范围已经定死了,查找a字符串的范围为0~s.size() - a.size();
    //满足上述条件之后还有一个就是从i开始,长度也已经定死了,只能是这个长度
    //2.s[i ~ (i + a.size() - 1)] == a
        
    //3.j范围已经定死了,查找b字符串的范围为0~s.size() - b.size();
    //满足上述条件之后还有一个就是从j开始,长度也已经定死了,只能是这个长度
    //4.s[j ~ (j + b.size() - 1)] == b
    
    //满足上述条件之后
    //5.abs(j - i) <= k
    
    int findAndRecord(string& source,string& target,vector<int>& positions)
    {
      int pos = source.find(target);
      while (pos != std::string::npos)
      {
        positions.push_back(pos);
        pos = source.find(target, pos + 1);
      }
      return positions.size(); // 返回找到的位置数量
    }
    bool st[110000];
    vector<int> beautifulIndices(string s, string a, string b, int k) 
    {
        memset(st,0,sizeof(st));
        int i_index_max = s.size() - a.size();
        int j_index_max = s.size() - b.size();//上述都是闭区间,下标
        
        int i_size_max = a.size();//固定a字符串长度
        int j_size_max = b.size();//固定b字符串长度
        vector<int> a_index;//存放a字符串的起始下标
        vector<int> b_index;//存放b字符串的起始下标
        findAndRecord(s,a,a_index);
        findAndRecord(s,b,b_index);
        set<int> s_b_index;
        vector<int> res;
        for(int i = 0;i < b_index.size();i++) s_b_index.insert(b_index[i]);
        
        for(int i = 0;i < a_index.size();i++) cout<<a_index[i]<<" ";
        cout<<endl;
        for(int i = 0;i < b_index.size();i++) cout<<b_index[i]<<" ";
        cout<<endl;
        
        for(int i = 0;i < a_index.size();i++)
        {
            //-k<=j - i<=k
            int _i_index = a_index[i];
            if(st[_i_index]) continue;
            int zhen_j = _i_index - k;//j>=i-k
            int fu_j = k + _i_index;//j<=k+i
       
                  auto it_lower = s_b_index.lower_bound(zhen_j);
                  if(it_lower != s_b_index.end())
                  {
                    if((abs(*it_lower - _i_index) <= k))
                    {
                          res.push_back(_i_index);
                          st[_i_index] = true;
                    }
                  }
    
             
                auto it_upper = s_b_index.upper_bound(fu_j);
                if(st[_i_index]) continue;
                if(it_upper != s_b_index.end())
                {
                    if((abs(*it_upper - _i_index) <= k))
                    {
                        res.push_back(_i_index);
                        st[_i_index] = true;
                    }
                } 
            
        }
        return res;
    }
};

  • 14
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

乖的小肥羊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值