我正在尝试解决UVa problem 458 - decoder并且我想出了以下算法,该算法为我提供了样本输入数据的正确输出,但运行时间比允许的长。
public class Decoder {
public void decoder() {
Scanner sc = new Scanner(System.in);
while (sc.hasNext()) {
String line = sc.nextLine();
for (int i = 0; i < line.length(); i++) {
if(line.charAt(i)>=32 && line.charAt(i)<=126)
System.out.print((char) (line.charAt(i) - 7));
}
System.out.println();
}
}
}
我已经阅读了forums并且大多数解决方案非常相似,我一直在研究是否有办法避免 for 循环正在通过字符串运行打印出新的char。但是这个循环是不可避免的,这个算法的时间复杂度总是n ^ 2。
问题还提到只更改ASCII可打印值,这就是为什么我设置条件来检查它是否大于或等于32和126.根据Wikipedia这是可打印值的范围。< / p>
答案 0 :(得分:4)
避免将流解码为字符。如果您只需要支持ASCII,则可以使用字节。
以大块读取和写入数据,以避免功能/系统调用开销。
避免不必要的分配。目前,您正在为每一行分配新的字符串。
请勿将输入拆分为多行以避免非常小的行显示性能不佳。
示例:
public static void main(String[] args) throws IOException {
byte[] buffer = new byte[2048];
while (true) {
int len = System.in.read(buffer);
if (len <= 0) {
break;
}
for (int i = 0; i < len; i++) {
...
}
System.out.write(buffer, 0, len);
}
}
它将像处理二进制文件一样处理输入。对于每次迭代,它将最多2048个字节读入缓冲区,处理它们并将它们写入标准输出。当达到EOF并且read返回-1时,程序将结束。 2048通常是一个很好的缓冲区大小,但你可能想尝试不同的大小,看看哪个最好。
答案 1 :(得分:1)
永远不要将Scanner
用于长输入。扫描程序比其他读取Java输入的方式慢得令人难以置信,例如BufferedReader
。这个UVa问题看起来像一个有很长输入的问题。