• 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+篇,公众号对话框回复【数据结构与算法】、【算法】、【数据结构】中的任一关键词,获取系列文章合集。

    以上就是全部内容,如果大家有什么好的解法思路、建议或者其他问题,可以下方留言交流,点赞、留言、转发就是对我最大的回报和支持!

  • 相关阅读:
    在C#代码中应用Log4Net(二)典型的使用方式
    在C#代码中应用Log4Net(一)简单使用Log4Net
    Windows Azure Active Directory (2) Windows Azure AD基础
    Windows Azure Virtual Network (6) 设置Azure Virtual Machine固定公网IP (Virtual IP Address, VIP) (1)
    Windows Azure Active Directory (1) 前言
    Azure China (6) SAP 应用在华登陆 Windows Azure 公有云
    Microsoft Azure News(3) Azure新的基本实例上线 (Basic Virtual Machine)
    Microsoft Azure News(2) 在Microsoft Azure上运行SAP应用程序
    Microsoft Azure News(1) 新的数据中心Japan East, Japan West and Brazil South
    Windows Azure HandBook (2) Azure China提供的服务
  • 原文地址:https://www.cnblogs.com/xiaochuan94/p/11235674.html
Copyright © 2020-2023  润新知