【问题标题】:Java simple application ComplexityJava 简单应用程序复杂性
【发布时间】:2017-03-27 09:01:49
【问题描述】:

我必须为面试解决一个问题,但我什么都不明白。 问题是,对于像“我们喜欢远足”这样的字符串,要像这样反转字符串:“ew ekil gnikih”,这意味着要像这样爆炸字符串:str.split(" ") 然后,每个单词要反转和添加到新字符串中。

问题出现在问题的最后,因为是在询问有关复杂性的问题,例如: “ - 预期的最坏情况时间复杂度为 O(N)” - 预期的最坏情况空间复杂度为 O(N)(不计算输入参数所需的存储空间)

我这样解决了这个问题:

public static String solution(String S){

    if(S.length()>1 && S.length()<200000){

        String toReturn = "";

        String[] splitted = null;
        if(S.contains(" ")){
            splitted = S.split(" ");
        }
        else{
            splitted = new String[]{S};
        }

        for(int i=0;i<=splitted.length-1;i++){
            String wordToChange = splitted[i];
            String reversedWord = "";
            for(int j=wordToChange.length()-1;j>=0;j--)
                reversedWord+=wordToChange.charAt(j);

            toReturn+=" " + reversedWord;

        }

        return toReturn.trim();

    }
    return null;
}

我应该如何处理复杂性请求? 谢谢!

【问题讨论】:

  • 你不明白什么?您是在问如何计算代码的时间复杂度/空间复杂度?
  • 是的,第一个问题是我的解决方案是否可行,以及如何计算复杂性,我必须对此请求做什么?

标签: java time-complexity space-complexity


【解决方案1】:

关于时间复杂度:

Worst-case O(N) 意味着您应该有一个最坏的情况,在这种情况下您计算 N 次迭代以获得结果,在您的情况下,您将字符串拆分为字符串数组 [操作可能需要 O (N),但这取决于方法 split()],然后对于数组中的每个字符串,您从字符串的末尾开始并反转字符。 所以你最坏的情况是 O(N) + O(N)... = O(N)

关于空间复杂度:

每个字符串都是一个对象,您在内存中为您创建的每个字符串保留空间,这里有一个字符串数组,这意味着您为从原始字符串中拆分的每个单词或字母创建一个对象。 你最坏的情况是一个像“I a m t h e o n e”这样的字符串,你为每个字符创建一个字符串-> O(N)

希望这能澄清你的疑惑

【讨论】:

    【解决方案2】:

    我认为至少在时间复杂度上这不是正确的答案。

    在我看来,字符串的拆分很可能是 O(n) 的复杂度。而且它只会增加下一个复杂性,因此我们可以忘记它。

    现在您正在创建一个空字符串并在每个字符串的顶部连接一个字符。在这里,您假设此操作与将值插入数组一样便宜 (O(1))。

    在这种情况下,您应该假设您每次都使用成员方法 concat() 创建一个新字符串。如果您有机会研究 String.concat(String) 的实现,您会看到此方法正在创建另一个 char[] 长度为 string1.length + string2.length 并复制 string1 和 string2进去。所以单独这个方法的复杂度是O(n)。

    因为您要为一个长度为 n 的单词连接 n 个字符,所以对于一个单词,它的复杂度为 O(n * (n / 2)) = O(n^2)。假设只有一个单词的最坏情况,您的复杂度等级为 O(n^2)。

    对于您的代码,我同意 O(n) 的空间复杂度类。但这只是假设 JVM 的智能重用你未使用的空间。

    您的代码应该可以工作,但我认为它确实不是解决这个问题的好代码。您可以使用 StringBuilder 或直接对 char[] 进行操作来改进它。

    StringBuilder 是个好主意,因为它的作用类似于 Vector 或 ArrayList。我在其背景中工作的 char[] 比字符串大得多。如果超过了它的容量(通过使用 append() 方法),它将创建一个更大的数组,类似于前一个支持数组大小的 2 倍。这可能只是 O(nlogn) 的时间复杂度。但是您可以通过使用与初始字符串相同大小的容量初始化 StringBuilder 来进一步调整它。这意味着支持 char[] 根本不会被复制,因为您不会超过它的容量。

    这是一个使用 char[] 的示例:

    private static void reverseCharArray(char[] result, int start, int end) {
        int halfDifference = (end - start) / 2;
        for (int i = 0; i < halfDifference; i++) {
            char buffer = result[start + i];
            result[start + i] = result[end - i - 1];
            result[end - i - 1] = buffer;
        }
    }    
    
    public static String reverseWordInString(String string) {
        char[] stringAsCharArray = string.toCharArray();
    
        int indexStart = 0;
        for (int indexEnd = 0; indexEnd < stringAsCharArray.length; indexEnd++) {
            if (stringAsCharArray[indexEnd] != ' ') {
                continue;
            }
            StringOperations.reverseCharArray(stringAsCharArray, indexStart, indexEnd);
            indexStart = indexEnd + 1;
        }
        StringOperations.reverseCharArray(stringAsCharArray, indexStart, stringAsCharArray.length);
    
        return String.valueOf(stringAsCharArray);
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-16
      • 1970-01-01
      • 2011-10-26
      • 2011-02-09
      • 1970-01-01
      • 2015-10-11
      相关资源
      最近更新 更多