目录
LeetCode459.找到重复的子字符串
链接: 459. 重复的子字符串 - 力扣(LeetCode)
方法一:暴力解法
1. 思路
暴力的解法, 就是一个for循环获取 子串的终止位置, 然后判断子串是否能重复构成字符串,又嵌套一个for循环,所以是O(n^2)的时间复杂度。
有的同学可以想,怎么一个for循环就可以获取子串吗? 至少得一个for获取子串起始位置,一个for获取子串结束位置吧。
其实我们只需要判断,以第一个字母为开始的子串就可以,所以一个for循环获取子串的终止位置就行了。 而且遍历的时候 都不用遍历结束,只需要遍历到中间位置,因为子串结束位置大于中间位置的话,一定不能重复组成字符串。
2. 代码实现
# 暴力解法
# time:O(N^2); space:O(1)
class Solution(object):
def repeatedSubstringPattern(self, s):
"""
:type s: str
:rtype: bool
"""
# 只要判断到字符串的中间位置就可以,
# 因为如果子串长度大于1/2字符串的长度,就不可能由这个重复的子串构成了
for i in range(len(s)//2):
# 截取子串字符串
Str = s[:i+1]
# 前提条件是主串长度可以被子串长度整除
if len(s)%len(Str) == 0:
# 这种Python的写法很棒
# 所有一段段的子字符串都满足条件
if all(s[j:j+len(Str)] == Str for j in range(i+1,len(s),len(Str))):
return True
return False
3. 复杂度分析
时间复杂度:O(N^2)
首先第一个for循环获取子串的结束位置,里面嵌套的for循环是逐个比较主串的元素,整体来说时间复杂度为O(N^2);
空间复杂度:O(1)
只用到了常数的空间储存子字符串
4. 思考
- Python语言的这种写法,可以记住应用:
if all(s[j:j+len(Str)] == Str for j in range(i+1,len(s),len(Str))):
return True
- 本题只需要遍历子串的结束位置以及只用遍历到字符串中间,这个是需要好好思考一下才能得到的结论,所以写代码之前要好好想想怎么尽可能通过思维上的结论去降低代码实现的复杂度。
方法二:移动匹配
1. 思路
当一个字符串s:abcabc,内部又重复的子串组成,那么这个字符串的结构一定是这样的:
也就是又前后又相同的子串组成。那么既然前面有相同的子串,后面有相同的子串,用 s + s,这样组成的字符串中,后面的子串做前串,前后的子串做后串,就一定还能组成一个s,如图:
所以判断字符串s是否有重复子串组成,只要两个s拼接在一起,里面还出现一个s的话,就说明是又重复子串组成。当然,我们在判断 s &