简单快速实现子序列的判断

 

针对力扣的判断子序列题目进行算法实现。原题链接可以点击地址:https://leetcode-cn.com/problems/is-subsequence/

基于近两年较火的力扣leetcode刷题训练站点,本人为了能够保持算法和数据结构这些底层计算机知识的基础牢固性,也时不时刷刷里面的题目,让自己的算法能力得到一个很好的锻炼,正所谓,“玉不琢不成器,人不学不知道”嘛。

这里我不想说太多,但是,练习多了,确实有一个很好的感悟。你会发现,所谓的这些算法,无论是针对数据结构的,还是针对数据处理的,提炼出来,都可以当作我们的人生算法,让我们能够更好地成长。像动态规划、贪婪算法、分而治之、递归、回溯等等。

以贪婪算法举例,我个人觉得这就是一个很好的策略。贪婪算法,说的就是获取局部的最优解,进而能够获取全局的最优解。人活在这个世界上,哪有那么容易一开始就能够获取最后美好结果的事情呢。我们长大到现在,实际上,都是一点一点地走过来,一步一步地做出各种选择。只不过这里面,作出了最好的那个选择,可能走得就要好一点,作出了坏一点的选择,就稍微要麻烦一些。那么,我们应该把握好当前能够获取的最优解,当一个个局部的最优解组合在一起时,能够获得最后的整体最优解。当然,凡是无绝对,但是,我觉得这个贪婪策略,还是适用于大部分情况的。

好了,不扯算法策略了。


题目如下:

判断子序列

给定字符串 s 和 t ,判断 s 是否为 t 的子序列。

你可以认为 s 和 t 中仅包含英文小写字母。字符串 t 可能会很长(长度 ~= 500,000),而 s 是个短字符串(长度 <=100)。

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

示例 1:
s = "abc", t = "ahbgdc"

返回 true.

示例 2:
s = "axc", t = "ahbgdc"

返回 false.
 


这里想说说的是,力扣官网有时候给出的权威题解,并不是最好的,你可以去看看其他的题解,获取更好的方法。对于该题而言,官方给出了双指针的算法,但是,我个人认为时间复杂度非常不好,因为需要执行最长字符串的长度次数,有点耗费计算机性能。当然了,对于现在的计算机而言,这个根本不算什们。但是,为了学习的话,我觉得还是需要去好好比较一下下的。

这里先给出官方的双指针思路及算法解释,当然,你也可以直接跳过我这里去看力扣官网的题解(官方解释)。

双指针方法的思路

本题询问的是,s 是否是 t 的子序列,因此只要能找到任意一种 s 在 t 中出现的方式,即可认为 s 是 t 的子序列。而当我们从前往后匹配,可以发现每次贪心地匹配靠前的字符是最优决策。

假定当前需要匹配字符 c,而字符 c 在 t 中的位置 x1 和 x2 出现(x1 < x2),那么贪心取 x1 是最优解,因为 x2 后面能取到的字符,x1也都能取到,并且通过 x1与 x2之间的可选字符,更有希望能匹配成功。

这样,我们初始化两个指针 i 和 j,分别指向 s 和 t 的初始位置。每次贪心地匹配,匹配成功则 i 和 j 同时右移,匹配 s 的下一个位置,匹配失败则 j 右移,i 不变,尝试用 t 的下一个字符匹配 s。

最终如果 i 移动到 s 的末尾,就说明 s 是 t 的子序列。

以Java代码为例,官方实现如下

class Solution {
    public boolean isSubsequence(String s, String t) {
        int n = s.length(), m = t.length();
        int i = 0, j = 0;
        while (i < n && j < m) {
            if (s.charAt(i) == t.charAt(j)) {
                i++;
            }
            j++;
        }
        return i == n;
    }
}

接下来分享本人的算法实现(力扣地址)

第一,以最短字符串为基准,循环迭代,分别获取位置由小到大的字符;
第二,设置字符串t的指针位置index,用于判断s的字符是否处于字符串t中的指针位置index到字符串尾部;
第三,如果s的字符处于字符串t的指定字符串范围中,则index加1,不断重复该操作;
第四,如果s的字符不处于字符串t的指定字符串范围中,则直接返回false;

这里先不解释太多,直接上代码

class Solution {
    public boolean isSubsequence(String s, String t) {
        if(s.length() > t.length()) return false;
        int index = 0;
        for(int i=0;i

相比于官方推荐的双指针,我这里稍微改变了一下,只是设置一个单独的指针,用于限定字符串的范围,进而判断出相应字符是否处于该字符串的范围内。

同时,循环遍历,是以最小的字符串为主,也就是待比较的子序列。这样,可以减少循环的次数,减少算法运行时间,虽然,这个时间对于计算机而言,可以忽略不计。我们也要以严谨的态度去研究和实现它。

在官网测试提交之后,得到了一个不错的结果。这也是判断算法优劣的标准。你或许已经想到了,那就是时间和空间复杂度。但从时间和空间复杂度考虑的话,实际上本人提供的算法和官方的算法是一样的。那就是时间复杂度为O(n),空间复杂度为O(1)。好像也看不出什么优劣出来。那么,我再比对一下执行效率吧,这是基于力扣站点反馈的信息。这里,你也可以自己去官方站点验证。

官方双指针的执行效率如下

简单快速实现子序列的判断_第1张图片

 

本人的算法执行效率如下

简单快速实现子序列的判断_第2张图片

 

故,算法没有最好,只能更好,相信,一定会有比我这个更加厉害的算法实现,也希望大家一起交流讨论。我想说,软件研发里面包含的思想,真的会对人生有着极大的用处。为什么,因为所有的思想落地,不就是通过软件落到实处了嘛。你会了分而治之,面对各种复杂的问题,还有什么担心的呢?你明白了贪婪策略,是不是就不会那么纠结了,就直接选择当下你最优的解就好。

最后,感谢你看到了这里,谢谢。

 

 

你可能感兴趣的:(算法,算法)