LeetCode.1071-字符串最大公約數(Greatest Common Divisor of Strings)


這是小川的第391次更新,第421篇原創

01 看題和准備

今天介紹的是LeetCode算法題中Easy級別的第253題(順位題號是1071)。對於字符串ST,當且僅當S = T + ... + TT與自身連接1次或更多次)時,我們說"T除S"

返回最大的字符串X,使得X除以str1X除以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 第一種解法

題目的要求是找出兩個字符串str1str2的最大公約數,即str1str2中都存在一個子串,並且都由這個子串重復出現一次或多次組成。

那么,什么情況下這兩字符串沒有最大公約數?

兩者分別前后拼接,但是不相等,那么肯定不存在最大公約數。例如示例中的str1 ="ABCABC"str2 ="ABC"str1拼接str2后變成"ABCABCABC"str2拼接str1后變成"ABCABCABC"。而str1 ="LEET"str2 ="CODE"str1拼接str2后變成"LEETCODE"str2拼接str1后變成"CODELEET",兩者顯然不相等,肯定不存在公約數。

那怎么找到他們的最大公約數呢?

思路:借助字符串拆分。用不同的子串分別對str1str2進行拆分,通過Stringsplit方法實現,如果拆分后的字符串數組中沒剩下任何元素,表明可以被該子串整除。找到兩字符串中長度較小的,作為循環次數上限,從后往前依次截取子串,將截取出來的子串用來拆分str1str2,如果拆分后得到的數組長度為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 第二種解法

和第一種解法思路類似,依舊是借助字符串的特性,使用替換來驗證最大公約數,通過StringreplaceAll方法實現。

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+篇,公眾號對話框回復【數據結構與算法】、【算法】、【數據結構】中的任一關鍵詞,獲取系列文章合集。

以上就是全部內容,如果大家有什么好的解法思路、建議或者其他問題,可以下方留言交流,點贊、留言、轉發就是對我最大的回報和支持!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM