判断子序列 —— LeetCode-392

1. 问题描述:

给定字符串 s 和 t ,判断 s 是否为 t 的子序列。字符串的一个子序列是原始字符串删除一些(也可以不删除)字符而不改变剩余字符相对位置形成的新字符串。(例如,"ace"是"abcde"的一个子序列,而"aec"不是)。

2. 示例:

示例 1:

输入:s = “abc”, t = “ahbgdc”
输出:true

示例 2:

输入:s = “axc”, t = “ahbgdc”
输出:false

3. 题解:

(1)双指针法

判断子序列 —— LeetCode-392_第1张图片
双指针法,顾名思义,使用两个指针ptr1,ptr2进行处理。详细过程为:将两个指针指向字符串初始位置,进行比较,如果相等,则两个指针都+1,均指向下一个元素;如果不相等,则只将原字符串(长的那个)ptr1指针+1即可。简单而言,就是找ptr2指向的元素,原字符串中是否出现。最终,如果ptr2指向了待匹配数组的下一个元素,则返回TRUE,否则返回FALSE。
显然,双指针法规模是遍历了两个字符串的每一个元素,因此时间复杂度为O(m + n)

(2)动态规划DP求解:

一般来说,DP求解的效率比较出色,但是博主认为LeetCode官方给出的题解的DP方法不是很巧妙(正在尝试优化),下面我价绍一下DP的方法:
双指针的核心思想就是按顺序寻找待匹配字符串的每个元素是否在原字符串出现过(在上一个元素出现过的位置之后找)。DP算法也是利用了这个思想,构建二维dp数组,dp[i][j]表示,原字符串数组中索引 i 之后出现元素 j 的位置。如:dp[2][2] = 4 表示,2号位置之后(包含下标为2的元素)第一次出现元素 ‘c’ 的位置是4。之所以是元素 ‘c’ ,是因为使用的ASCII码, a + 2 就是 c ,因此j的范围也是0~25之间,分别表示 a-z。规划方程如下:
判断子序列 —— LeetCode-392_第2张图片
然后考虑边界条件,原字符串 t 共m个元素,则索引为0~m-1,因此初始化f[m][i] = m,即只要指针移动到m,即f[i][j] = m , 则表示找不到元素 j,则直接返回FALSE

4. 代码:

(1)双指针法:

class Solution {
public:
    bool isSubsequence(string s, string t) {
        int n = s.length(), m = t.length();
        int i = 0, j = 0;
        while (i < n &&  < m) {
            if (s[i] == t[j]) {
                i++;
            }
            j++;
        }
        return i == n;
    }
};

判断子序列 —— LeetCode-392_第3张图片
由此可见,时间效率还是蛮不错的,能在线性时间内即可找到答案。

(2) 动态规划算法

class Solution {
public:
    bool isSubsequence(string s, string t) {
int n = s.size(), m = t.size();

        vector<vector<int> > f(m + 1, vector<int>(26, 0));
        for (int i = 0; i < 26; i++) {
            f[m][i] = m;
        }

        for (int i = m - 1; i >= 0; i--) {
            for (int j = 0; j < 26; j++) {
                if (t[i] == j + 'a')
                    f[i][j] = i;
                else
                    f[i][j] = f[i + 1][j];
            }
        }
        int add = 0;
        for (int i = 0; i < n; i++) {
            if (f[add][s[i] - 'a'] == m) {
                return false;
            }
            add = f[add][s[i] - 'a'] + 1;
        }
        return true;
    }
};

判断子序列 —— LeetCode-392_第4张图片
显然时间复杂度和空间复杂度远远劣于双指针法,说明此题解并不是一个很好的DP方案。

你可能感兴趣的:(算法,算法,动态规划)