这是我的解决方案中的一个问题的解决方案。通过我的推论,我得出结论,它具有总体O(N ^ 2)时间复杂度。但是,我想对此进行确认,以便在判断算法的时间/空间复杂性时,我不会继续犯同样的错误。
哦,问题如下:
给定输入字符串,逐字反转字符串。 例如"我是你" =="你是我"
代码如下: -
public String reverseWords(String s) {
//This solution is in assumption that I am restricted to a one-pass algorithm.
//This can also be done through a two-pass algorithm -- i.e. split the string and etc.
if(null == s)
return "";
//remove leading and trailing spaces
s = s.trim();
int lengthOfString = s.length();
StringBuilder sb = new StringBuilder();
//Keeps track of the number of characters that have passed.
int passedChars = 0;
int i = lengthOfString-1;
for(; i >= 0; i--){
if(s.charAt(i) == ' '){
//Appends the startOfWord and endOfWord according to passedChars.
sb.append(s.substring(i+1, (i+1+passedChars))).append(" ");
//Ignore additional space chars.
while(s.charAt(i-1) == ' '){
i--;
}
passedChars = 0;
}else{
passedChars++;
}
}
//Handle last reversed word that have been left out.
sb.append(s.substring(i+1, (i+1+passedChars)));
//return reversedString;
return sb.toString();
}
我的理由是O(N ^ 2)算法: -
就此而言,如果其他人有更好的解决方案,请随时分享! :)
我的目标是一次通过解决方案,因此选择在循环之前拆分字符串。
感谢帮助!
编辑:我想问一下包含循环的代码部分的时间复杂度。如果这个问题误导/混淆,我会提前道歉。整个代码块用于澄清目的。 :)
答案 0 :(得分:5)
时间复杂度为O(n)
。
append(x)
的每次插入(StringBuilder
)都在O(|x|)
完成,其中| x |}是要附加的输入字符串的大小。 (平均而言,与建造者的状态无关。)
您的算法会迭代整个字符串,并对其中的每个字词使用String#substring()
。由于单词不重叠,这意味着您每次为每个单词执行substring()
,并将其附加到构建器(也是一次) - 为每个单词2|x|
提供x
。
总结一下,给你
T(S) = |S| + sum{2|x| for each word x}
但是从sum{|x| for each word x} <= |S|
开始,这给你总计:
T(S) = |S| + 2sum{|x| for each word x} = |S| + 2|S| = 3|S|
因为| S |是输入的大小(n
),这是O(n)
请注意,重要的部分是在jdk7中,substring()
方法在输出字符串的大小上是线性的,而不是原始的(您只复制相关部分,而不是所有字符串)。
答案 1 :(得分:1)
这是另一种解决方案,我认为可能会有所改善。
public String reverseWords(String s) {
String[] array = s.split(" ");
int len = array.length;
StringBuilder sb = new StringBuilder();
for (int i = 0; i < len; i++) {
sb.append(" ").append(array[len - i - 1]);
}
return sb.toString().trim();
}
答案 2 :(得分:1)
Amit已经给你详细的复杂度计算解释,我想给你一个更简单的版本。
通常,如果我们有嵌套循环,我们认为复杂度为O(N ^ 2)。但事实并非如此,因为你必须为每个输入的第n部分做n次活动。例如,如果输入大小为3,则必须对每个元素执行3次操作。然后,您可以说您的算法具有O(n ^ 2)复杂度。
由于您只遍历和处理输入字符串的每个部分(即使您使用的是嵌套循环),因此复杂性应该是O(n)的顺序。为了证明,阿米特做了很多工作。
虽然,我会使用下面的代码来颠倒单词的顺序
String delim = " ";
String [] words = s.split(delim);
int wordCount = words.length;
for(int i = 0; i < wordCount / 2; i++) {
String temp = words[i];
words[i] = words[wordCount - i - 1];
words[wordCount - i - 1] = temp;
}
String result = Arrays.toString(words).replace(", ", delim).replaceAll("[\\[\\]]", "");