524. 通过删除字母匹配到字典里最长单词(双指针,子序列匹配)

 

 双指针的子序列匹配问题,老样子,对于双指针问题,应该先写出暴力怎么做

class Solution {
public:
    string findLongestWord(string s, vector<string>& dictionary) {
        sort(dictionary.begin(),dictionary.end(),[](const auto &a,const auto &b)
        {
            if(a.size()!=b.size())
                return a.size()<b.size();
            else
                for(int i=0;i<a.size();i++)
                    if(a[i]!=b[i])
                        return a[i]>b[i];
            return false;
        });
        for(int k=dictionary.size()-1;k>=0;k--)
        {
            string aim=dictionary[k];
            for(int i=0;i<s.size();i++)
            {   
                int l=0,valid=0;
                if(aim[l]!=s[i]) continue;
                for(int j=i;j<s.size();j++)
                {
                    if(aim[l]==s[j]) valid++,l++;
                    if(valid==aim.size()) return aim; 
                }
            }                    
        }
        return "";
    }
};

虽然暴力可以ac,但是还是用双指针优化一下

其实我们发现,我们的第二重第三重循环,只需要保留一个循环就可以了

暴力:先找到一个左端点,固定左端点,然后延伸右端点直到满足或者尾部

换一个左端点,右端点会清零

双指针优化:先找到一个左端点,固定左端点,延伸右端点直到满足或者维护

换一个右端点,右端点不会清零

int valid=0,l=0;
for(int i=0,j=0;i<s.size();)
{
     if(j<i) j=i;
     if(s[i]!=aim[0])
     {
           i++;
           continue;
     }
     while(j<s.size()&&valid<aim.size())
     {
          if(aim[l]==s[j]) valid++,l++;
          j++;
     }
     if(valid==aim.size())  return aim;
     i++;
}    

其实这样子的双指针也是使用了双指针---维护区间信息的特性(即滑动窗口),我们其实可以不用维护一个窗口,直接从0开始枚举到尾部,查看有没有存在这个字典就行了(因为题目要求的是是否存在,而不是要求窗口最小)

于是进一步优化如下

string findLongestWord(string s, vector<string>& dictionary) {
        sort(dictionary.begin(),dictionary.end(),[](const auto &a,const auto &b)
        {
            if(a.size()!=b.size())
                return a.size()<b.size();
            else
                for(int i=0;i<a.size();i++)
                    if(a[i]!=b[i])
                        return a[i]>b[i];
            return false;
        });
        for(int k=dictionary.size()-1;k>=0;k--)
        {
            string aim=dictionary[k];
            int valid=0,l=0;
            for(int i=0;i<s.size();)
            {   
                if(aim[l]==s[i]) l++,valid++;
                if(valid==aim.size())  return aim;
                i++;
            }             
        }
        return "";
    }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值