英文:
Convert text line of integers into array of integers in fastest way
问题
我有一个小作业,我需要将包含10,000个数字的文本行转换为整数。我尝试了下面的代码:
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int[] a = Arrays.stream(br.readLine().split("\\s+")).mapToInt(Integer::parseInt).toArray();
它有效,但速度仍然不够快,我遇到了时间限制错误。有没有办法让它运行得更快?
英文:
I have a small homeworks, I need to convert text line of integers contains 10,000 numbers. I have tried this code below:
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int[] a = Arrays.stream(br.readLine().split("\\s+")).mapToInt(Integer::parseInt).toArray();
It's worked, but it's still not fast enough and I got Time Limited Exeeded error. Is there any way I can make it run faster?
答案1
得分: 2
一种方法是使用 Scanner 类,并迭代使用 Scanner#nextInt 方法。
Scanner scanner = new Scanner(System.in);
int[] a = new int[10_000];
int index = 0;
while (index < a.length) a[index++] = scanner.nextInt();
英文:
One way is to use the Scanner class, and iterate on the Scanner#nextInt method.
Scanner scanner = new Scanner(System.in);
int[] a = new int[10_000];
int index = 0;
while (index < a.length) a[index++] = scanner.nextInt();
答案2
得分: 0
正则表达式和整数转换可能会很方便,但不一定高效。在您发布的代码中,正则表达式评估器必须检查每个字符以找到分隔符,然后为它找到的每个数字创建一个新字符串,并调用转换例程以创建整数(这涉及再次查看字符串的每个字符)。底层工作量很大。
您可以考虑在单个步骤中进行解析和转换。如果您知道输入是有效的(即没有超出范围的值,也没有非数字字符),那么沿着这些线路编写的高效循环可能会起作用。请注意,我并不是一个真正的Java程序员,但您应该能够理解这个想法的要点:
List<Integer> tempList; // 这是一个动态列表,通过附加进行增长
String inputString;
inputString = br.readLine();
int i = 0; // 数字在这里构建
boolean firstDigit = false;
for (int x = 0; x < inputString.length(); x++) {
if (inputString.charAt(x) == ' ') {
// 如果输入字符是空格并且您至少看到了一个数字,则这是该数字的结尾。
// 将其写入输出列表并重置。
if (firstDigit) {
tempList.add(i);
i = 0;
firstDigit = false;
}
continue; // 继续获取下一个字符
}
i = (i * 10) + (inputString.charAt(x) - '0');
firstDigit = true;
}
// 我们已经到达了字符串的末尾。
// 可能末尾没有空格,所以最后一个值仍然在变量i中,尚未写入输出
if (firstDigit) {
tempList.add(i);
}
// 然后将可扩展列表转换为数组
return tempList.toArray(new Integer[0]);
这样做可能会更快,因为它只需一次遍历数组中的每个字符。此外,它不会创建任何临时字符串。
如果您知道在一行上确切有10,000个数字,您可以通过在开始时分配返回数组来进一步提高速度。当您读取一个数字时,将其添加到数组并增加索引。类似于:
int a[10000];
int aIndex = 0;
然后在您的循环中,替代 tempList.add(i)
的部分是:
a[aIndex] = i;
aIndex++;
这将消除对动态列表和最后的 ToArray
的需要。
英文:
You might find that the regular expression and integer conversion are convenient but not necessarily performant. In the code you posted, the regex evaluator has to examine every character to find the separators, then create a new string for each number it finds, and call the conversion routine to create an integer (which involves looking at each character of the string again). There's a lot of work going on under the hood.
You might consider parsing and converting in a single step. If you know that the input is valid (i.e. there aren't any values out of range and there aren't any non-numeric characters), then a tightly coded loop along these lines might do the trick. Note that I'm not really a Java programmer, but you should be able to get the gist of the idea:
List<int> tempList; // this is a dynamic list that grows with append
string inputString;
inputString = br.readLine();
int i = 0; // number is built here
bool firstDigit = false;
for (x = 0 to length of inputString) {
if (inputString[x] == ' ') {
// if the input character is a space and you've seen
// at least one digit, then this is the end of that number.
// Write it to the output list and reset.
if (firstDigit) {
tempList.append(i);
i = 0;
firstDigit = false;
}
continue; // go get next character
}
i = (i*10) + inputString[x] - '0';
firstDigit = true;
}
// We've reached the end of the string.
// There might not be a space at the end, so the last value
// is still in the variable i and hasn't been written to output
if (firstDigit) {
tempList.append(i);
}
// and then convert that expandable list to an array
return tempList.ToArray()
This could potentially be much faster because it goes through the array examining each character exactly once. In addition, it doesn't create any temporary strings.
If you know that there are exactly 10,000 numbers on the line, you can speed this up even more by allocating your return array at the start. When you read a number, add it to the array and increment the index. Something like:
int a[10000];
aindex = 0;
And then in your loop in place of tempList.append(i)
, you have:
a[aindex] = i;
aindex++;
That will eliminate the need for the dynamic list and the ToArray
at the end.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论