题目:
对于字符串 s
和 t
,只有在 s = t + t + t + ... + 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
由大写英文字母组成
解题思路:
首先考虑最大公因数的概念,指能够整除多个非零整数的最大正整数。例如8和12的最大公因数为4。
解决这个数学问题的常见方法是辗转相除法,计算gcd(18,48)时,先将48除以18得到商2、余数12,然后再将18除以12得到商1、余数6,再将12除以6得到商2、余数0,即得到最大公因数6。我们只关心每次除法的余数是否为0,为0即表示得到答案。
如果将辗转相除法转换为数学表达式,则如下所示:
很明显这是个可以转化为递归的表达式。
而题目所要求的字符串最大公约式和传统的数字公约数不同,每次去除的子字符串需要相同(即a-b的b需要相同)
代码:
class Solution {
public String gcdOfStrings(String str1, String str2) {
int len1 = str1.length();
int len2 = str2.length();
if(len1 == len2 && str1.equals(str2))
return str1;
else if(len1>len2 && str2.equals(str1.substring(len1-len2,len1)))
return gcdOfStrings(str1.substring(0,len1-len2),str2);
else if(len2>len1 && str1.equals(str2.substring(len2-len1,len2)))
return gcdOfStrings(str1,str2.substring(0,len2-len1));
else
return "";
}
}
更简洁的思路与代码:
在str1和str2拼接时如果交换顺序,拼接结果不变,则存在最大公约数。
此时,如果str1的长度是len1,str2的长度是len2,则长度为len1和len2的最大公约数的前缀,就是最大公约式。
扩展:
substring可以用于分割子字符串,替代数字减法。
对于substring这个函数,需要注意有两种形式,
public String substring(int beginIndex)
public String substring(int beginIndex, int endIndex)
-
beginIndex -- 起始索引(包括), 索引从 0 开始。
-
endIndex -- 结束索引(不包括)