Java简单应用程序复杂性

Java简单应用程序复杂性,java,time-complexity,space-complexity,Java,Time Complexity,Space Complexity,我必须为面试解决一个问题,但我不明白什么。 问题是,对于像“we like徒步旅行”这样的字符串来说,将字符串反转成这样:“ew ekil gnikih”,这意味着将字符串分解成:str.split(“”),然后将每个单词反转并添加到新字符串中 问题在问题的末尾,因为我们在问一些关于复杂性的问题,比如: “-预期的最坏情况时间复杂度为O(N)” -预期wors案例空间复杂度为O(N)(不计算输入参数所需的存储) 我这样解决了这个问题: public static String solution(

我必须为面试解决一个问题,但我不明白什么。 问题是,对于像“we like徒步旅行”这样的字符串来说,将字符串反转成这样:“ew ekil gnikih”,这意味着将字符串分解成:str.split(“”),然后将每个单词反转并添加到新字符串中

问题在问题的末尾,因为我们在问一些关于复杂性的问题,比如: “-预期的最坏情况时间复杂度为O(N)” -预期wors案例空间复杂度为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;
}
公共静态字符串解决方案(字符串S){
如果(S.length()>1和&S.length()关于时间复杂性:

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

关于空间复杂性:

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

希望这能澄清您对时间复杂性的疑问

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

关于空间复杂性:

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


希望这能澄清您的疑问

我认为这不是正确的答案,至少在时间复杂性方面是如此

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

现在,您正在创建一个空字符串,并在每个字符串的顶部连接一个字符

在本例中,您应该假设每次都使用成员方法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是个好主意,因为它的行为类似于向量或ArrayList。我在其后台工作的char[]比字符串大得多。如果超出了它的容量(通过使用append()方法),它将创建一个更大的数组,大约是前一个备份数组大小的2倍。这可能只是O(nlogn)的时间复杂度。但您可以通过初始化与初始字符串大小相同的StringBuilder来进一步调整它。这意味着备份字符[]不会被复制,因为您不会超过它的容量

下面是一个使用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);
}
private static void reverseCharArray(char[]result,int start,int end){
int半差=(结束-开始)/2;
对于(int i=0;i
至少就时间复杂性而言,我认为这不是正确的答案

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

现在,您正在创建一个空字符串,并在每个字符串的顶部连接一个字符

在本例中,您应该假设每次都使用成员方法concat()创建一个新字符串。如果您有机会查看String.concat(String)的实现,您将看到此方法正在创建另一个字符串长度的char[]