1071.字符串的最大公因子

解題思路

定理:兩個整數(shù)的最大公約數(shù)等于其中較小的那個數(shù)和兩數(shù)相除余數(shù)的最大公約數(shù)。最大公約數(shù)(Greatest Common Divisor)縮寫為GCD。
gcd(a,b) = gcd(b,a mod b) (不妨設(shè)a>b 且r=a mod b ,r不為0)

gcd(a,b) = b if a%b == 0 else gcd(b,a%b)
或者
gcd(a,b) = a if b==0 else gcd(b,a%b)

注意到一個性質(zhì):如果存在一個符合要求的字符串 X,那么也一定存在一個符合要求的字符串 X',它的長度為 str1 和 str2 長度的最大公約數(shù)。

簡單來說,我們已經(jīng)知道符合條件的長度出現(xiàn)在 gcd(len_1, len_2)的所有約數(shù)中,我們假設(shè)其中一個滿足條件的約數(shù)為x,該長度為 len_x的前綴串 X 能經(jīng)過若干次拼接后得到 str1 和 str2。拿 str1 舉例,X 經(jīng)過 len_1/len_x 次拼接后得到了 str1,而 X 又能經(jīng)過 gcd(len_1, len_2)/len_x 次拼接后得到長度為 gcd(len_1,len_2)的前綴串 X',所以我們可以每次取出 gcd(len_1, len_2)/len_x 個 X 來用 X'完成替換,最后 str1 會被替換成 len_1/gcd(len_1,len_2) 個 X',str2 同理可得。因此如果存在一個符合要求的字符串 X,那么也一定存在一個符合要求的字符串 X',它的長度為 str1 和 str2 長度的最大公約數(shù)。我們只需要判斷長度為 gcd(len_1,len_2)的前綴串是否滿足要求即可。

算法
由上述性質(zhì)我們可以先用輾轉(zhuǎn)相除法求得兩個字符串長度的最大公約數(shù) gcd(len_1,len_2),取出該長度的前綴串,判斷一下它是否能經(jīng)過若干次拼接得到 str1 和 str2 即可。

復(fù)雜度分析:
時間復(fù)雜度:O(n),其中 n 是兩個字符串的長度范圍,即 len_1 + len_2 。判斷最大公約數(shù)長度的前綴串是否符合條件需要 O(n) 的時間復(fù)雜度,求兩個字符串長度的最大公約數(shù)需要 )O(logn) 的時間復(fù)雜度,所以總時間復(fù)雜度為 O(n+logn)=O(n)。
空間復(fù)雜度:O(n),比較的過程中需要創(chuàng)建一個長度創(chuàng)建長度為 O(n) 的臨時字符串變量,所以需要額外 O(n) 的空間。

代碼

class Solution:
    def gcdOfStrings(self, str1: str, str2: str) -> str:
        m, n = len(str1), len(str2)
        if m < n:
            return self.gcdOfStrings(str2, str1)
        def gcd(a,b):
            return b if a%b==0 else gcd(b, a%b)
        r = gcd(m, n)
        if (str1[:r] == str2[:r] and str1[:r]*(len(str1)//r) == str1 and str2[:r]*(len(str2)//r) == str2):
            return str1[:r]
        return ""
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容