74.字符串的最大公因子
题目链接
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/greatest-common-divisor-of-strings
题目描述
对于字符串 S 和 T,只有在 S = T + ... + T(T 与自身连接 1 次或多次)时,我们才认定 “T 能除尽 S”。
返回最长字符串 X,要求满足 X 能除尽 str1 且 X 能除尽 str2。
示例 1:
输入:str1 = "ABCABC", str2 = "ABC"
输出:"ABC"
示例 2:
输入:str1 = "ABABAB", str2 = "ABAB"
输出:"AB"
示例 3:
输入:str1 = "LEET", str2 = "CODE"
输出:""
提示:
1 <= str1.length <= 1000
1 <= str2.length <= 1000
str1[i] 和 str2[i] 为大写英文字母
关键技术
最大公约数(Greatest Common Divisor)缩写为GCD
gcd定理:两个整数的最大公约数等于其中较小的那个数和两数相除余数的最大公约数
gcd算法:gcd(a,b) = gcd(b,a mod b) (不妨设a>b 且r=a mod b ,r不为0)
题目分析
我首先想到的做法:
- 定义两个空数组:res1,res2;
- 分别遍历str1,str2;
- 判断res1中是否第一次出现str1的字符,若是第一次出现,就把这个字符放到res1中,str2也是如此;
- 判断res1和res2是否相同,如果相同就说明res1或res2是str1和str2“最大公约字符串”。
没有AC的原因:没有考虑到“最大公约字符串”中包含重复的字符。
var gcdOfStrings = function(str1, str2) { let res1 = ''; for(let i=0;i<str1.length;i++){ if(res1.indexOf(str1[i]) == -1){ res1 += str1[i]; } } let res2 = ''; for(let i=0;i<str2.length;i++){ if(res2.indexOf(str2[i]) == -1){ res2 += str2[i]; } } if(res1 == res2){ return res1; }else{ return ""; } };
然后我就看了题解,学到了gcd算法,具体分析如下:
- 判断str1 + str2 是否与 str2 + str1不全等,这是考虑到字符串拼接,如果存在最大公因子,那么拼接起来就会相等,例如:str1 = "ABCABC", str2 = "ABC",str1 + str2 = "ABCABCABC",str2 + str1 = "ABCABCABC",str1 + str2 === str2 + str1。
- 两个字符串的最大公因子的字符串长度是两个字符串长度的最大公约数,例如:str1 = "ABCABC", str2 = "ABC",str1.length = 6,str1.length = 3,最大公因子:"ABC“,最大公约数:3。
- 根据求出的最大公约数,使用substring函数截取字符串。
/** * @param {string} str1 * @param {string} str2 * @return {string} */ var gcdOfStrings = function(str1, str2) { if(str1 + str2 !== str2 + str1){ return ""; } function gcd(a,b){ if(b === 0){ return a; } return gcd(b, a % b); } return str1.substring(0, gcd(str1.length,str2.length)); };
简写:
/** * @param {string} str1 * @param {string} str2 * @return {string} */ var gcdOfStrings = function(str1, str2) { if(str1 + str2 !== str2 + str1){ return ""; } function gcd(a,b){ return b ===0 ? a : gcd(b, a % b); } return str1.substring(0, gcd(str1.length,str2.length)); };