LeetCode.1071-字符串最大公约数(Greatest Common Divisor of Strings)
这是小川的第391次更新,第421篇原创
01 看题和准备
今天介绍的是LeetCode算法题中Easy级别的第253题(顺位题号是1071)。对于字符串S
和T
,当且仅当S = T + ... + T
(T
与自身连接1次或更多次)时,我们说"T除S"
。
返回最大的字符串X
,使得X
除以str1
,X
除以str2
。
例如:
输入:str1 ="ABCABC",str2 ="ABC"
输出:"ABC"
输入:str1 ="ABABAB",str2 ="ABAB"
输出:"AB"
输入:str1 ="LEET",str2 ="CODE"
输出:""
注意:
-
1 <= str1.length <= 1000
-
1 <= str2.length <= 1000
-
str1[i]
和str2[i]
是英文大写字母。
02 第一种解法
题目的要求是找出两个字符串str1
、str2
的最大公约数,即str1
、str2
中都存在一个子串,并且都由这个子串重复出现一次或多次组成。
那么,什么情况下这两字符串没有最大公约数?
两者分别前后拼接,但是不相等,那么肯定不存在最大公约数。例如示例中的str1 ="ABCABC"
,str2 ="ABC"
,str1
拼接str2
后变成"ABCABCABC"
,str2
拼接str1
后变成"ABCABCABC"
。而str1 ="LEET"
,str2 ="CODE"
,str1
拼接str2
后变成"LEETCODE"
,str2
拼接str1
后变成"CODELEET"
,两者显然不相等,肯定不存在公约数。
那怎么找到他们的最大公约数呢?
思路:借助字符串拆分。用不同的子串分别对str1
和str2
进行拆分,通过String
的split
方法实现,如果拆分后的字符串数组中没剩下任何元素,表明可以被该子串整除。找到两字符串中长度较小的,作为循环次数上限,从后往前依次截取子串,将截取出来的子串用来拆分str1
和str2
,如果拆分后得到的数组长度为0,则此子串就是最大公约数。
public String gcdOfStrings(String str1, String str2) {
if (!(str1+str2).equals(str2+str1)) {
return "";
}
int n = Math.min(str1.length(), str2.length());
for (int i=n; i>=1; i--) {
String temp = str2.substring(0, i);
if (str2.split(temp).length == 0 &&
str1.split(temp).length == 0) {
return temp;
}
}
return "";
}
03 第二种解法
和第一种解法思路类似,依旧是借助字符串的特性,使用替换来验证最大公约数,通过String
的replaceAll
方法实现。
public String gcdOfStrings2(String str1, String str2) {
if (!(str1+str2).equals(str2+str1)) {
return "";
}
int n = Math.min(str1.length(), str2.length());
for (int i=n; i>=1; i--) {
if (n%i != 0) {
continue;
}
String temp = str2.substring(0, i);
if(str1.replaceAll(temp,"").equals("") &&
str2.replaceAll(temp,"").equals("")) {
return temp;
}
}
return "";
}
04 第三种解法
我们还可以从数学角度来思考这个问题。
思路:将两个字符串的长度看做求最大公约数的两个整数,单独写一个求两个数最大公约数的算法,算出最大公约数后,取两字符串中长度较小的,截取子串,子串的长度就是前一步算出的最大公约数,该子串也就是我们最后要返回的两字符串的最大公约数。
public String gcdOfStrings3(String str1, String str2) {
if (!(str1+str2).equals(str2+str1)) {
return "";
}
int len = str1.length();
int len2 = str2.length();
int gcd = GCD(len, len2);
if (len < len2) {
return str1.substring(0, gcd);
}
return str2.substring(0, gcd);
}
public int GCD(int a, int b) {
if (b == 0) {
return a;
}
return a % b == 0 ? b : GCD(b, a % b);
}
05 第四种解法
我们还可以将第三种解法中用到的求最大公约数的递归方法,和字符串操作整合在一起。
找到两个字符串中长度较大的那个,如果长度大的字符串包含较小长度字符串的所有字符,就用长度较小的字符串对较大中的子串进行替换,直到有一方为空串为止。
public String gcdOfStrings4(String str1, String str2) {
if (str1.length() < str2.length()) {
return gcdOfStrings4(str2, str1);
}
if (str2.isEmpty()) {
return str1;
}
if (!str1.contains(str2)) {
return "";
}
str1 = str1.replace(str2, "");
return gcdOfStrings4(str2, str1);
}
06 小结
算法专题目前已连续日更超过七个月,算法题文章259+篇,公众号对话框回复【数据结构与算法】、【算法】、【数据结构】中的任一关键词,获取系列文章合集。
以上就是全部内容,如果大家有什么好的解法思路、建议或者其他问题,可以下方留言交流,点赞、留言、转发就是对我最大的回报和支持!