力扣 392. 判断子序列 dp双指针

    科技2026-01-26  12

    https://leetcode-cn.com/problems/is-subsequence/ 思路:有一个显然正确的贪心:对于任意一个字符 i i i,假设可选的匹配位置有 p o s 1 、 p o s 2 pos_1、pos_2 pos1pos2,且 p o s 1 < p o s 2 pos_1<pos_2 pos1<pos2,那么应该选择 p o s 1 pos_1 pos1而不是 p o s 2 pos_2 pos2。双指针的做法就不说了,说一下后续挑战怎么搞。第一个思路我们用 v e c [ i ] [ j ] vec[i][j] vec[i][j]记录字符串 t t t中第 j + 1 j+1 j+1次出现的字符 i i i的位置,然后再遍历一次字符串 s s s,根据贪心选取最靠前的位置即可。

    class Solution { public: bool isSubsequence(string s, string t) { vector<int> vec[26]; int siz=t.size(); for(int i=0;i<siz;i++) vec[t[i]-'a'].push_back(i); bool flag=true; int pos=-1,idx; siz=s.size(); for(int i=0;i<siz&&flag;i++){ idx=upper_bound(vec[s[i]-'a'].begin(),vec[s[i]-'a'].end(),pos)-vec[s[i]-'a'].begin(); if(idx==vec[s[i]-'a'].size()) flag=false; else pos=vec[s[i]-'a'][idx]; } return flag; } };

    上面这个思路比较节省空间,但是时间复杂度要比 O ( l e n ( s ) ) O(len(s)) O(len(s))高一点,大概要再乘个 l o g log log。我们可以把上面的数组转换一下,用 v e c [ i ] [ j ] vec[i][j] vec[i][j]记录从字符串 t t t的位置 i i i开始,字符 j j j出现的第一个位置。这样时间复杂度就可以降到 O ( l e n ( s ) ) O(len(s)) O(len(s))了,但是空间复杂度和初始化的时间复杂度较高。

    class Solution { public: bool isSubsequence(string s, string t) { int siz=t.size(); vector<vector<int>> vec(siz+1,vector<int>(26)); for(int i=0;i<26;i++) vec[siz][i]=siz; for(int i=siz-1;i>=0;i--){ for(int j=0;j<26;j++){ if(t[i]=='a'+j) vec[i][j]=i; else vec[i][j]=vec[i+1][j]; } } int n=s.size(),idx=0; for(int i=0;i<n;i++){ idx=vec[idx][s[i]-'a']; if(idx==siz) return false; ++idx; } return true; } };
    Processed: 0.013, SQL: 9