浅谈第二阶段刷力扣的体验

浅谈第二阶段刷力扣的体验

一、前言

我陆陆续续刷力扣也有一段时间了,从开始的绞尽脑汁也不会到现在略了解知晓怎么做,但具体做不做的出来还是一个很大问题,还有就是有些算法,数据结构以及思想还未踏进,所以欠缺的还是很多。这里有我现在做题的体会,希望能够分享给大家,以及记录我刷题的经历。

二、题目

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

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

进阶:

如果有大量输入的 S,称作 S1, S2, ... , Sk 其中 k >= 10亿,你需要依次检查它们是否为 T 的子序列。在这种情况下,你会怎样改变代码?

示例 1:

输入:s = "abc", t = "ahbgdc"
输出:true
示例 2:

输入:s = "axc", t = "ahbgdc"
输出:false

三、代码过程
class Solution {
    public boolean isSubsequence(String s, String t) {
        
        //1.利用暴力  (连续子序列) 
        //说明:我首先想到的是暴力双循环,但是我在做的过程中不知不觉做成了求解连续子序列问题,
        //所以这是我们做题的一个通病:拿到题就开始做,等到代码写的差不多的时候才发现与题目要求
        //的不一样。这需要我们认真理解题目。
        int m = s.length();
        int n = t.length();
        if (m > n){
            return false;
        }
        for (int i = 0; i < n - m; i++){
            int count = 0;
            for (int j = 0; j < m; j++){
                if (t.charAt(i + j) == s.charAt(j)){
                    count++;
                }
            }
            if (count == m){
                return true;
            }
        }
        return false;

        //2.子序列
        //说明:我通过知道上面有问题的时候,才转换成这问题对应的双循环求解。与上面差不多。
        int n = t.length();
        int m = s.length();
        if (m > n) {
            return false;
        }
        int index = 0;
        int count = 0;
        for (int i = 0; i < m; i++){
            for (int j = index; j < n; j++){
                if (s.charAt(i) == t.charAt(j)){
                    count++;
                    index = j + 1;
                    break;
                }
            }
        }
        if (count == m){
                return true;
            }
        return false;

        //3.indexOf()	
        //说明3:做完后发现,实现效率不高,有没有其他方法降低时间空间复杂度呢?在浏览力扣评论
        //的时候(我一般看题解在评论里面找),看见一个代码很干练的,即利用indexOf()java函数,
        //时间复杂度大大降低,原因是因为indexOf()采用了KMP算法,有兴趣的可以仔细研究这个
        //算法时间复杂度是多少?m ? m + n ? m * n ? 欢迎评论
        int index = -1;
        for (char c : s.toCharArray()){
            index = t.indexOf(c, index + 1);
            if (index == -1){
                return false;
            }
        }
        return true;

        //4.dp 
        //说明4:我做完暴力我就想到是不是可以用dp动态规划来做,但是动态规划还是比较不容易想的,
        //有兴趣可以看看我之前的动态规划讲解,这无疑有是一种解题思路
        int m = s.length();
        int n = t.length();
        int [][]dp = new int[m + 1][n + 1]; //表示s长度为m 的和t长度为n 的相同子序列长度
        for (int i = 1; i <= m; i++){
            for (int j = 1; j <= n; j++){
                if (s.charAt(i - 1) == t.charAt(j - 1)){ //找到字符串s下标为i和字符串t下标为j
                										//的相同字符
                    dp[i][j] = dp[i - 1][j - 1] + 1; //找到长度加1
                }else{
                    dp[i][j] = dp[i][j - 1]; //没找到则是原来长度的值
                }
            }
        }
        if (dp[m][n] == m){
            return true;
        }
        return false;


    }
}
四、总结

作为刚开始刷题的我们来讲,最好的方法就是看人家是怎么做的,然后大致了解实现过程和能够代码敲出来。不需要完全理解这道题后再往下看,因为这样会让你丢失为数不多的耐心和兴趣,然后也是费时费力,强迫理解。度过这一阶段后,就是需要解题联想,一道题有多种算法能够实现,各自的时间空间复杂度也不一样,这就要求我们的知识性扩展性如何了。通常顺序是:暴力->其他算法,有更多的算法实现思维能够帮助我们提高代码的执行效率,找到最优解。

posted @ 2022-07-17 17:15  何泽  阅读(80)  评论(0)    收藏  举报