编写代码以仅使用一次isSubstring调用来检查s2是否是s1的旋转

时间:2014-09-07 14:44:22

标签: java string algorithm stringbuffer

假设您有一个方法isSubstring,它检查一个单词是否是另一个单词的子串。给定两个字符串s1和s2,编写代码以仅使用一次调用IsSubstring来检查s2是否是s1的旋转

(例如," waterbottle"旋转" erbottlewat")

以下是我的代码:

public class IsRotation1_8 {

    /*
     * Idea: Same idea as the code in CC150 book
     * First, if the s2 is a rotation of s1, they should have the same length
     * Then, check whether the s2 is a subString of s1 + s1
     *
     * Time Complexity: O(n)
     * Space Complexity: O(n)
     */
    private static boolean isRotation(String s1, String s2) {
        if (s1.length() != s2.length()) {
            return false;
        }
        String s3 = s1 + s1;
        // return isSubString(s3, s2);
        return isSubString2(s3, s2);
    }

    private static boolean isSubString(String s3, String s2) {
        return s3.contains(s2);
        // return s3.indexOf(s2)!=-1;
    }

    /*
     * Implement the isSubString method without using the method of Contains and indexOf
     */
    private static boolean isSubString2(String s3, String s2){
        int lengthS3 = s3.length();
        int lengthS2 = s2.length();
        for (int i = 0; i < lengthS3; i++) {
            int j = i;
            int k = 0;
            while(s2.charAt(k++) == s3.charAt(j++)){
                if(k == lengthS2)
                    return true;
            }
        }
        return false;
    }

    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        System.out.println("Please enter string1 (q to quit):");

        while (input.hasNextLine()) {
            String string1 = input.nextLine();
            if (string1.equals("q")) {
                System.out.println("quit...");
                System.exit(0);
            }
            System.out.println("Please enter string2:");
            String string2 = input.nextLine();

            System.out.println("Is s2 a rotation of s1?(solution1) :"
                    + isRotation(string1, string2));
            System.out.println();
            System.out.println("Please enter another string1 (q to quit): ");
        }
    }
}

它很好地实现了问题,但我对此有一些疑问

  1. 我不知道如何计算此解决方案的时间复杂度,它似乎取决于isSubString方法,String.contains()方法的时间复杂度是什么?
  2. 如果我使用自己的isSubString方法而不是String.contains()方法,即使这里有两个循环,时间复杂度也是O(n)
  3. 一位朋友告诉我O(n)如果使用String,O(1)如果使用StringBuilder,不计算isSubstring()方法的时间,是吗?有人可以具体解释一下吗?
  4. 我知道String是不可变的,并且StringBuffer是可变的,并且在使用String时,每次添加字符或执行某些操作时,它都会创建一个新的String,但Stringbuffer不会。

    但我认为它不会影响时间的复杂性。 在这个解决方案中,即使使用String,它也只是产生一个新的String

1 个答案:

答案 0 :(得分:1)

  1. Java的文档并没有限制String.contains的实现来使用特定的算法。如果算法是例如Knuth-Morris-Pratt,那么运行时间将是线性的。如果算法是天真的,那么运行时间将是二次的。

  2. isSubString2实现了朴素算法,这是最坏情况的二次算法。

  3. 忽略优化,每个String级联的成本等于组合字符串的长度,但每个StringBuilder附加的(摊销)成本等于附加字符串的长度。正如您在此处使用的那样,单个String连接始终是线性时间,但切换到StringBuilder以进行重复追加是明智的,以避免多次偿还第一个字符的成本。 / p>