這是小川的第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+篇,公眾號對話框回復【數據結構與算法】、【算法】、【數據結構】中的任一關鍵詞,獲取系列文章合集。
以上就是全部內容,如果大家有什么好的解法思路、建議或者其他問題,可以下方留言交流,點贊、留言、轉發就是對我最大的回報和支持!