目录
今日任务:
- 字符串总结
-
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