字符串的最大公因子
对于字符串
s
和t
,只有在s = t + ... + t
(t
自身连接 1 次或多次)时,我们才认定 “t
能除尽s
”。给定两个字符串
str1
和str2
。返回 最长字符串x
,要求满足x
能除尽str1
且x
能除尽str2
。示例 1:
输入:str1 = "ABCABC", str2 = "ABC" 输出:"ABC"
示例 2:
输入:str1 = "ABABAB", str2 = "ABAB" 输出:"AB"
示例 3:
输入:str1 = "LEET", str2 = "CODE" 输出:""
提示:
1 <= str1.length, str2.length <= 1000
str1
和str2
由大写英文字母组成
O(n2)
class Solution:
def gcdOfStrings(self, str1: str, str2: str) -> str:
res: list = []
for i in range(len(str2)):
_str = str2[:i + 1]
_num1 = len(str1) // len(_str)
_num2 = len(str2) // len(_str)
if _num1 * _str == str1 and _num2 * _str == str2:
if len(str1) % len(_str) == 0 and len(str2) % len(_str) == 0:
res.append(_str)
if not res:
return ""
else:
res = res[-1]
return "".join(res)
递归版O(n)
class Solution:
def gcdOfStrings(self, str1: str, str2: str) -> str:
if str1+str2 != str2+str1:
return ''
difference = len(str1)-len(str2)
if difference==0:
return str1
elif difference > 0:
str1 = str1[len(str2): len(str1)]
else:
str2 = str2[len(str1): len(str2)]
return self.gcdOfStrings(str1,str2)
优化版O(n)
class Solution:
def gcdOfStrings(self, str1: str, str2: str) -> str:
if not str1 or not str2:
return str1 if str1 else str2
if len(str1) < len(str2):
return self.gcdOfStrings(str2, str1) # Ensure str1 is not shorter than str2
if not str1.startswith(str2):
return "" # If str1 doesn't start with str2, they don't have a common divisor
return self.gcdOfStrings(str1[len(str2):], str2) # Delete the prefix of str1 that equals str2
在这个问题中,我们应当使用欧几里得算法,它常用于计算两个整数的最大公约数,但也可以用于解决这个问题。基本思想是“辗转相除”:如果两个字符串有最大公共因子(GCD),那么整个 str1
和 str2
都应该是由 GCD 重复若干次构成的,这个性质对 str1
和 str2
的任何前缀都应该成立。因此,我们可以不断将较长的字符串替换为其和较短字符串的差,即删除它的前缀,直到两个字符串相等,那么这个字符串就是 GCD,或者其中一个字符串变成空字符串,那么说明它们没有 GCD。
这个实现确保了如果 str1
不以 str2
开头,那么它们没有公共的因子,所以直接返回空字符串。否则,就删除 str1
的前缀 str2
,然后递归地寻找 str1[len(str2):]
和 str2
的最大公共因子。最终,如果其中一个字符串变成空字符串,那么另一个字符串就是最大公共因子。
这个实现的时间复杂度是 O(N),其中 N 是 str1
和 str2
的总长度,因为在最坏的情况下,它需要检查 str1
和 str2
的每个字符。空间复杂度也是 O(N),因为 Python 的字符串切片操作会创建新的字符串。这个实现没有使用任何额外的数据结构,所以空间效率较高。