优化方法的性能

时间:2020-04-01 01:25:54

标签: java

有两个字符串-st

查找字符串s是否可被字符串t整除。如果可以将字符串t连接若干次以获得字符串s,则字符串s可被字符串t整除。 如果s是可整除的,请找到最小的字符串u,以便可以将其串连几次以获得s和t。 如果不能整除,则将返回值设置为-1。 最后,返回字符串u或-1的长度。

示例1:

s =“ bcdbcdbcdbcd”

t =“ bcdbcd”

如果字符串t被串联两次,则结果为“ bcdbcdbcdbcd”,它等于字符串s。字符串s可被字符串t整除。

自从通过第一个测试以来,寻找可以连接以创建字符串s和t的最小字符串u。

字符串“ bcd”是可以连接在一起以创建字符串s和t的最小字符串。

字符串u的长度为3,这是要返回的整数值。

示例2:

s =“ bcdbcdbcd”

t =“ bcdbcd”

如果将字符串t连接两次,则结果为“ bcdbcdbcdbcd”,它大于字符串s。串联的字符串中有一个额外的“ bcd”。

字符串s不能被字符串t整除,因此返回-1。

我有以下代码,但它很“慢”-长字符串需要一段时间。有什么可以优化的呢?这类问题的“正确”算法是什么?

public static void main(String[] args) {
    String s1 = "bcdbcdbcdbcd", t1 = "bcdbcd";
    String s2 = "bcdbcdbcd", t2 = "bcdbcd";
    String s3 = "lrbb", t3 = "lrbb";
    System.out.println(getLength(s1, t1));
    System.out.println(getLength(s2, t2));
    System.out.println(getLength(s3, t3));
}

private static int getLength(String s, String t) {
    if(s.length() % t.length() > 0)
        return -1;
    StringBuilder sb = new StringBuilder();
    for(int i=0;i*t.length() < s.length();i++) {
        sb.append(t);
    }
    if(!sb.toString().equals(s))
        return -1;
    for(int i=1;i<=t.length();i++) {
        sb = new StringBuilder();
        String subStr = t.substring(0, i);
        while(sb.length() < t.length()) {
            sb.append(subStr);
        }
        if(sb.toString().equals(t))
            return i;
    }
    return -1;
}

3 个答案:

答案 0 :(得分:0)

在代码的第二部分中,即使sb不能被t整除,即subStr时,您仍要尝试构建t.length() % i > 0。 / p>

不知道t的最大长度是多少,但是如果t是例如一个61的字符串,即使您只应检查StringBuilderappend() ,由于您正在创建61个i = 1对象并调用i = 61 322次(自61是素数)

即使61检查也是多余的,因为您知道t本身可以被整除。

进行以下更改:

  • i<=t.length()更改为i<t.length()

  • 在循环内添加以下内容:

    if (t.length() % i > 0)
        continue;
    
  • 将最后一个return -1;更改为return t.length();


在Java 11+中,我们在repeat()上有了了不起的新String方法,它比使用StringBuilder快得多,因此使用Java 11可以将代码缩短为:

private static int getLength(String s, String t) {
    if (s.length() % t.length() != 0 || ! s.equals(t.repeat(s.length() / t.length())))
        return -1;
    for (int i = 1; i < t.length(); i++)
        if (t.length() % i == 0 && t.equals(t.substring(0, i).repeat(t.length() / i)))
            return i;
    return t.length();
}

答案 1 :(得分:0)

第二个for循环只需要检查t.length()的因数,这将使它大大加快。

答案 2 :(得分:0)

KMP 算法是一种可以用 O(n) 有效求解的算法。 This 示例将帮助您在 O(n) 中解决此问题。

第一部分即 "求字符串 s 是否能被字符串 t 整除" 很简单,您可以通过在 StringBuilder(sb) 中附加 t 直到 某人的长度

对于第二部分,即 “如果 s 是可整除的,找到最小的字符串 u,这样它可以连接若干次以获得 s 和 t”。 KMP 算法的“后缀和前缀的最长子串”技术将有助于以优化的方式解决这个问题。