代码随想录算法训练营第9天 | 字符串总结 + 双指针回顾

目录

今日任务:

字符串总结:

关于是否使用库函数:

双指针法:

反转系列:

KMP算法:

28.strStr()实现

str.find(): 

 str.index():

KMP:

(前缀和不减1)

 459.重复的字符串

 巧解:

KMP:

 ​编辑


今日任务:

  • 字符串总结
  • 28.实现strStr()

  • 459.重复字符串的字符串


字符串总结:

关于是否使用库函数:

        打基础的时候,不要太迷恋于库函数。习惯于调用split,reverse之类的库函数,却不知道其实现原理,也不知道其时间复杂度,这样实现出来的代码,如果在面试现场,面试官问:“分析其时间复杂度”的话,一定会一脸懵逼!

        建议如果题目关键的部分直接使用库函数就可以解决,就不要使用库函数。如果库函数仅仅只是解题过程中的一小部分,并且你已经很清楚这个库函数的内部实现原理的话,可以使用库函数。

双指针法:

         在344.反转字符串,我们使用双指针法实现了反转字符串的操作,双指针法在数组、链表和字符串中都很常用。

        接着在字符串:替换空格,同样还是使用双指针法在时间复杂度O(n)的情况下完成替换空格。其实很多数组填充类的问题,都可以预先给数组扩容带填充后的大小,然后再从后向前操作。

        针对数组删除操作的问题,在27. 移除元素 中就已经提到了使用双指针法进行移除操作。同样的道理在151.翻转字符串里的单词中我们是使用O(n)的时间复杂度,完成了删除冗余空格。

反转系列:

        反转其实考察的就是对代码的掌控能力。

        中,一些同学可能为了处理逻辑:每隔2k个字符的前k的字符,写了一堆逻辑代码或者再搞一个计数器,来统计2k,再统计前k个字符。其实当需要固定规律一段一段去处理字符串的时候,要想想在在for循环的表达式上做做文章。只要让 i += (2 * k),i 每次移动 2 * k 就可以了,然后判断是否需要有反转的区间。因为要找的也就是每2 * k 区间的起点,这样写程序会高效很多。

KMP算法:


28.strStr()实现

题目链接:28. 找出字符串中第一个匹配项的下标 - 力扣(LeetCode)

分析:

  • 典型的KMP算法,解决字符串匹配的问题
  • python str.find()函数使用的是BM和horspool两种算法,horspool 平均时间复杂度是 O(n),BM 算法最好情况下时间复杂度可以达到 O(n/m)。而KMP的时间复杂度为O(n)
  • str.index(str, beg=0 end=len(string))

    参数

    str -- 此选项指定要搜索的字符串。

    beg -- 这是开始索引,默认情况下是 0。

    end -- 这是结束索引,默认情况下它等于该字符串的长度。

str.find(): 

class Solution:
    def strStr(self, haystack: str, needle: str) -> int:
        return haystack.find(needle)

 str.index():

class Solution:
    def strStr(self, haystack: str, needle: str) -> int:
        try:
            return haystack.index(needle)
        except ValueError:
            return -1

KMP:

(前缀和不减1)

class Solution:
    def getNext(self, next:List[int], s: str) -> None:
        j = 0
        next[0] = 0

        for i in range(1, len(s)):
            while j > 0 and s[j] != s[i]:
                j = next[j - 1]
            
            if s[i] == s[j]:
                j += 1
            
            next[i] = j
    
    def strStr(self, haystack: str, needle:str) -> int:
        
        next = [0] * len(needle)
        self.getNext(next, needle)
        j = 0
        for i in range(len(haystack)):

            while j > 0 and haystack[i] != needle[j]:
                j = next[j - 1]
            
            if haystack[i] == needle[j]:
                j += 1
            
            if j == len(needle):
                return i - len(needle) + 1
        
        return -1


 459.重复的字符串

题目链接:459. 重复的子字符串 - 力扣(LeetCode)

 分析:

        我自己理解的是如果s不包含重复子串,那么s自己就是一次重复的子串,那么把s + s去头去尾中就一定不包含s自己。如果s包含重复子串,那么在s + s去头去尾中就一定能找到s自己(来自:力扣解析)

 巧解:

class Solution:
    def repeatedSubstringPattern(self, s: str) -> bool:
        return True if s in (s+s)[1: -1] else False

KMP:

class Solution:
    def getNext(self, next:List[int], s:str) -> None:
            j = 0
            next[0] = 0
            
            for i in range(1, len(s)):
                while j > 0 and s[i] != s[j]:
                    j = next[j-1]

                if s[i] == s[j]:
                    j += 1

                next[i] = j

    def repeatedSubstringPattern(self, s: str) -> bool:
        next = [0] * len(s)
        self.getNext(next, s)

        if next[len(s) - 1] != 0 and len(s) % (len(s) - next[len(s) - 1]) == 0:
            return True
        else:
            return False
        

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值