Java 简单的应用程序复杂性
Java simple application Complexity
我为了面试解决了一个问题,有什么没看懂。
问题是,对于像 "we like hiking" 这样的字符串,要像这样反转字符串:"ew ekil gnikih",这意味着,要像这样分解字符串:str.split(" ") 然后,每个词到反转并添加到新字符串。
问题在问题的最后,因为在问一些关于 Complexity 的问题,比如:
“ - 预期的最坏情况时间复杂度为 O(N)”
- 预期的最坏情况 space 复杂度为 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;
}
我应该如何处理复杂性请求?
谢谢!
关于时间复杂度:
最坏情况 O(N) 意味着你应该有一个最坏的情况,在这种情况下你计算 N 次迭代以获得结果,在你的情况下你将字符串拆分为一个字符串数组[操作可能需要 O(N),但它取决于方法 split()],然后对于数组中的每个字符串,您从字符串的末尾开始并反转字符。
所以你最坏的情况是 O(N) + O(N)... = O(N)
大约 space 复杂度:
每个字符串都是一个对象,你在内存中为你创建的每个字符串保留 space,这里你有一个字符串数组,意味着你为从原始拆分出来的每个单词或字母创建一个对象细绳。
最坏的情况是像 "I a m t h e o n e" 这样的字符串,您在其中为每个字符创建一个字符串 -> O(N)
希望这能澄清你的疑惑
我认为至少在时间复杂度上这不是正确答案。
在我看来,字符串的拆分很可能是 O(n) 的复杂度。它只会增加下一个复杂性,因此我们可以忘记它。
现在您要创建一个空字符串并在每个字符串顶部连接一个字符。在这里,您假设此操作与将值插入数组一样便宜 (O(1))。
在这种情况下,您应该假设,您每次都在使用成员方法 concat() 创建一个新的字符串。如果您有机会查看 String.concat(String) 的实现,您会发现此方法正在创建另一个长度为 string1.length + string2.length 的 char[] 和正在将 string1 和 string2 复制到其中。所以单独这个方法的复杂度为O(n).
因为您要将 n 个字符连接到一个长度为 n 的单词,所以它的复杂度为 O(n * (n / 2)) = O(n^2) 一个单词。假设只有一个单词的最坏情况,您的复杂度为 O(n^2).
class
我同意您的代码的 space 复杂度 class O(n)。但这只是在 JVM 的智能重用你未使用的假设下 space.
你的代码应该可以工作,但我认为它不是解决这个问题的好代码。您可以使用 StringBuilder 或直接对 char[].
进行操作来改进它
StringBuilder 是个好主意,因为它的行为类似于 Vector 或 ArrayList。我在其后台工作的 char[] 比 String 大得多。如果超出容量(通过使用 append() 方法),它将创建一个更大的数组,大约是前一个后备数组大小的 2 倍。这可能只是 O(nlogn) 的时间复杂度。但是您可以通过使用与初始 String 相同大小的容量初始化 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);
}
我为了面试解决了一个问题,有什么没看懂。 问题是,对于像 "we like hiking" 这样的字符串,要像这样反转字符串:"ew ekil gnikih",这意味着,要像这样分解字符串:str.split(" ") 然后,每个词到反转并添加到新字符串。
问题在问题的最后,因为在问一些关于 Complexity 的问题,比如: “ - 预期的最坏情况时间复杂度为 O(N)” - 预期的最坏情况 space 复杂度为 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;
}
我应该如何处理复杂性请求? 谢谢!
关于时间复杂度:
最坏情况 O(N) 意味着你应该有一个最坏的情况,在这种情况下你计算 N 次迭代以获得结果,在你的情况下你将字符串拆分为一个字符串数组[操作可能需要 O(N),但它取决于方法 split()],然后对于数组中的每个字符串,您从字符串的末尾开始并反转字符。 所以你最坏的情况是 O(N) + O(N)... = O(N)
大约 space 复杂度:
每个字符串都是一个对象,你在内存中为你创建的每个字符串保留 space,这里你有一个字符串数组,意味着你为从原始拆分出来的每个单词或字母创建一个对象细绳。 最坏的情况是像 "I a m t h e o n e" 这样的字符串,您在其中为每个字符创建一个字符串 -> O(N)
希望这能澄清你的疑惑
我认为至少在时间复杂度上这不是正确答案。
在我看来,字符串的拆分很可能是 O(n) 的复杂度。它只会增加下一个复杂性,因此我们可以忘记它。
现在您要创建一个空字符串并在每个字符串顶部连接一个字符。在这里,您假设此操作与将值插入数组一样便宜 (O(1))。
在这种情况下,您应该假设,您每次都在使用成员方法 concat() 创建一个新的字符串。如果您有机会查看 String.concat(String) 的实现,您会发现此方法正在创建另一个长度为 string1.length + string2.length 的 char[] 和正在将 string1 和 string2 复制到其中。所以单独这个方法的复杂度为O(n).
因为您要将 n 个字符连接到一个长度为 n 的单词,所以它的复杂度为 O(n * (n / 2)) = O(n^2) 一个单词。假设只有一个单词的最坏情况,您的复杂度为 O(n^2).
class我同意您的代码的 space 复杂度 class O(n)。但这只是在 JVM 的智能重用你未使用的假设下 space.
你的代码应该可以工作,但我认为它不是解决这个问题的好代码。您可以使用 StringBuilder 或直接对 char[].
进行操作来改进它StringBuilder 是个好主意,因为它的行为类似于 Vector 或 ArrayList。我在其后台工作的 char[] 比 String 大得多。如果超出容量(通过使用 append() 方法),它将创建一个更大的数组,大约是前一个后备数组大小的 2 倍。这可能只是 O(nlogn) 的时间复杂度。但是您可以通过使用与初始 String 相同大小的容量初始化 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);
}