2、字符串的最大公因子

194 阅读2分钟

原题力扣《字符串的最大公因子》

难度简单

题目:对于字符串 s 和 t,只有在 s = t + t + t + ... + t + t(t 自身连接 1 次或多次)时,我们才认定 “t 能除尽 s”。

给定两个字符串 str1 和 str2,返回 最长字符串 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, str2.length <= 1000
  • str1 和 str2 由大写英文字母组成

解题:JS

个人:硬解

  1. 除尽指的是 str = n * x => str / x = n(整数)
/**
 * @param {string} str1
 * @param {string} str2
 * @return {string}
 */
var gcdOfStrings = function (str1, str2) {
    let base = ''

    let i = 0;

    while (i < str1.length || i < str2.length) {
        base += str1.slice(0, i)
        if (str1.split(base).join('') || str2.split(base).join('')) {
            i++
        }
    }

    return base
};

没解出来

解题耗时:16 min


官方:最大公约数、辗轧相除法

约数:相除后余数为零,就可以称为约数,4 % 2 = 0,则 2 是 4 的约数

思路1:

  1. 这个思路是没问题的:除尽指的是 str = n * x => str / x = n(整数),那表明存在某个字符串 x
  2. 那一定存在这个逻辑:str1.length % x.length === str2.length % x.length === 0
  3. 并且为了取得最大公约数,就需要从最长的开始循环往下找
  4. 题目简化为:求 4、6 的最大公约数,x 从 6 开始递减,若 4、6 都除尽 x,则找到 x 了
// 判断字符串 str 是否除尽字符串 x
var checkString = function (x, str) {
    // 通过 JS 的 replaceAll 来判断
    return str.replaceAll(x, "") === "";
};

var gcdOfStrings = function (str1, str2) {
    const len1 = str1.length;
    const len2 = str2.length;

    let x = ''

    let maxstr = len1 > len2 ? str1 : str2;

    for (let maxlen = maxstr.length; maxlen > 0; maxlen--) {
        // 判断长度是否除尽
        if (len1 % maxlen === 0 && len2 % maxlen === 0) {
            const _x = maxstr.slice(0, maxlen);

            if (checkString(_x, str1) && checkString(_x, str2)) {
                x = _x;
                break;
            }
        }
    }

    return x;
};

执行用时,消耗内存

64 ms,49.32 MB


思路2:str1 = n * x;str2 = m * x可推导出str1 + str2 = (n+m) * x = m * x + n * x = str2 + str1

所以重点来了,若存在最大公约数,那 str1 + str2 一定等于 str2 + str1

那最大公约数的字符串为gcd(str1.length, str2.length)的字符串。

// gcd 求公约数的函数
const gcd = (a, b) => (b === 0 ? a : gcd(b, a % b))

var gcdOfStrings = function (str1, str2) {
  if(str1 + str2 !== str2 + str1) return ''
  return str1.slice(0, gcd(str1.length, str2.length))
}

执行用时,消耗内存

50 ms,49.38 MB


总结:还是那句话,做算法一定要去找到对应的解题名称,而不是从语言层面去硬解。刚开始看到公约数了,但没有公约数的算法知识,所以第一次硬解没做出来