LeetCode每日一题(1) 字符串最大公因子

前言

从今天开始每天一道leetcode,从简单的开始,加油!!!

废话不多说了,先上题目。

题目描述
对于字符串 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. 1 <= str1.length <= 1000
  2. 1 <= str2.length <= 1000
  3. str1[i] 和 str2[i] 为大写英文字母

解法

解法一:
**解法一应该是最普遍的,也是我最先想到的。**利用两个字符串的最大公约数来判断,如果,两个字符串符合题目叙述,即存在X,使得len(X)是len(str1),len(str2)的最大公约数。(因为X是最长的字符串)。我们假设str1更长。因此,我们只要求得两个字符串长度的最大公约数,并且使得:
str1[:len(X)]*(len(str1)//len(X))str1,str2同str1处理,那么X就等于str1[:len(X)].

class Solution:
    def gcdOfStrings(self, str1: str, str2: str) -> str:
    	# 求的最大公约数
        candidate_len = math.gcd(len(str1),len(str2))
        # 获得X(是str1的前缀)
        candidate = str1[: candidate_len]
        if candidate*(len(str1)//candidate_len)==str1 and candidate*(len(str2)//candidate_len)==str2:
            return candidate
        return ""

解法二
这个解法用到了辗转相减。
由题目知:
若str1+str2 != str2+str1,那么就不符合题意,即返回""。

若两个字符串长度相等并且str1+str2 == str2+str1(注意顺序不同)。那么X就是str1(str2)。

若长度不等,但是str1+str2 == str2+str1,那么第一次拿较长的串减去较短的串后得一个余串。第二次拿第一次两个相减字符串中的短串和余串相比一直到两个串相等,那这个最终的串就是X。(总是拿长串减去短串)

输入:str1 = “ABABAB”, str2 = “ABAB”
输出:“AB”

如上面的这个示例:
先拿str1-str2,余"AB".第二次用“ABAB”-“AB”得“AB”,第三次时,两个都是“AB”故得X=“AB”

class Solution:
    def gcdOfStrings(self, str1: str, str2: str) -> str:
    	# 先判断两个字符串符合条件不不
        if str1+str2 != str2+str1:
            return ""
        # str1和str2相减
        di = len(str1)-len(str2)
        # 若大于0,则str1较长,从str1中剔除str2
        if di>0:
            str1 = str1[len(str2):len(str1)]
        # 若相等,则返回此时得str1(str2也行,反正都一样)
        elif di==0:
            return str1
        # 若小于0,则str2较长,从str2中剔除str1
        else:
            str2 = str2[len(str1):len(str2)]
        # 递归
        return self.gcdOfStrings(str1,str2)

解法三
这个解法一般人想不到的…它的前半部分依旧是求两个字符串的最大公约数。依旧取得前缀字符串。只不过后续的判断变简单了。
当str1+str2==str2+str1时即可说明这个前缀字符串是X。

数学思想

(1)第一个字符串是str1+ str2,第二个字符串时str2+str1。
(2)我们给他们进行分段上色上,str1有5段 并且涂了5种不同的颜色(比如红、橙、黄、绿、青),str2 有3段并且涂了3种不同的颜色(蓝、紫、白),那么一共有8种颜色,每个颜色代表一些内容;再把两个字符串拼接,得到第一个字符串str1+str2,第二个字符串str2+str1;
(3)我们的前提假设是拼接后的两个大串,即第一个字符串和第二个字符串是相同的,第一个字符串颜色为{红橙黄绿青蓝紫白},第二个字符串顺序为{蓝紫白红橙黄绿青},因为两个串相同,那么有8组对应{红-蓝}、{橙-紫}等,因为相等,把颜色替换掉,比如红替换蓝等,
全部替换完之后会发现最后只剩一种颜色,说明str1和str2都是由这个颜色组成并且不会有更长的,那这个颜色代表的这段就是str1和str2的最大公因子;
(4)你也可以假设str1有6段,涂6种颜色,str2有3段,涂3种颜色,再对应相等并替换,结果就会看到是str2的3段是最大公因子。

class Solution:
    def gcdOfStrings(self, str1: str, str2: str) -> str:
        candidate_len = math.gcd(len(str1),len(str2))
        candidate = str1[: candidate_len]
        if str1+str2 == str2+str1:
            return candidate
        return ""
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值