我有以下代码,用参数-Xmx<1024M>
运行需要5秒钟以上。
我知道for
循环需要O(q)
时间,而reverse()
和toString()
分别需要O(n)
时间。
是否有一种方法可以在不到O(n)
的时间内反转字符串?还是其他原因使代码速度变慢?任何帮助都将受到欢迎!
class Main {
public static void main(String[] args){
String s = "a";
String qa = "200000";
int q = Integer.parseInt(qa);
String[] t = new String[q];
for(int i = 0; i < q; i++) {
if(i%2==0) {t[i] = "2 1 x";}
if(i%2==1) {t[i] = "1";}
if(t[i].toCharArray()[0] == '1') {
StringBuilder rev = new StringBuilder(s).reverse();
s = rev.toString();
} else {
char letter = t[i].toCharArray()[4];
if(t[i].toCharArray()[2] == '1') {
s = letter + s;
} else {
s = s + letter;
}
}
}
System.out.println(s);
}
}
答案 0 :(得分:4)
不管应该做什么(我不知道),我发现了以下问题:
StringBuilder
的多个实例化。+
运算符的字符串连接。Sring::toCharArray
(请参阅第二种解决方案)仅使用StringBuilder
的一个实例,您将获得更快的结果:
String s = "a";
String qa = "200000";
int q = Integer.parseInt(qa);
String[] t = new String[q];
StringBuilder sb = new StringBuilder(s); // Instantiate before the loop
for (int i = 0; i < q; i++) {
if(i%2==0) {t[i] = "2 1 x";}
if(i%2==1) {t[i] = "1";}
if(t[i].toCharArray()[0] == '1') {
sb.reverse(); // all you did here is just reversing 's'
} else {
char letter = t[i].toCharArray()[4];
if(t[i].toCharArray()[2] == '1') {
sb.insert(0, letter); // prepend a letter
} else {
sb.append(letter); // append a letter
}
}
}
另一件事是,您多次定义了诸如t[i] = "2 1 x";
之类的字符串,然后将其与t[i].toCharArray()[0]
进行比较。预先定义这些不可变的值,使用char[][]
也会有所帮助:
String s = "a";
String qa = "200000";
int q = Integer.parseInt(qa);
char[][] t = new char[q][]; // char[][] instead of String[]
char[] char21x = new char[]{'2', '1', 'x'}; // predefined array
char[] char1 = new char[]{'1'}; // another predefined array
StringBuilder sb = new StringBuilder(s); // Instantiate before the loop
for (int i = 0; i < q; i++) {
if(i%2==0) {t[i] = char21x;} // first reuse
if(i%2==1) {t[i] = char1;} // second reuse
if(t[i][0] == '1') { // instead of String::toCharArray, mind the indices
sb.reverse(); // all you did here is just reversing 's'
} else {
char letter = t[i][2]; // instead of String::toCharArray, mind the indices
if(t[i][1] == '1') {
sb.insert(0, letter); // prepend a letter
} else {
sb.append(letter); // append a letter
}
}
}
编辑:我已经使用笔记本电脑上的System.currentTimeMillis()
进行了最简单的测试:
7.658
,6.899
和7.046
秒3.288
,3.691
和3.158
秒2.717
,2.966
和2.717
秒结论:我认为无法从算法复杂度方面改善算法本身,但是,使用正确的方法处理String有助于将时间复杂度降低2-3倍(在我看来情况)。
一般建议:您可以在循环之前实例化和定义什么,在循环之前进行。
答案 1 :(得分:-1)
有没有一种方法可以在不到O(n)的时间内反转字符串?还是其他原因使代码速度变慢?
没有办法在少于O(n)的时间内反转字符串:产生大小为n的输出的程序必须最少花费o(n)的时间。
您的代码中有许多不必要的操作,这些操作会使程序变慢。该程序产生50000个字母x,然后是一个字母a,然后是另一个50000个字母x。这是同一程序的更快(更容易理解)的实现。
class Faster {
public static void main(String[] args) {
String hundredXs = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
for (int i = 0; i < 500; i++)
System.out.print(hundredXs);
System.out.print("a");
for (int i = 0; i < 500; i++)
System.out.print(hundredXs);
System.out.println();
}
}