我遇到与此类似的任务有问题: click (translated)(我被指派的那个有更大的测试和更短的时间限制)。快速翻译任务:
编写一个程序,检查给定序列中给定数字的出现次数。
输入:给定数字,序列中有多少个数字,数字序列
输出:出现次数
到目前为止我的解决方案:
1
#!/usr/bin/env perl
while (<>) {
$in = $_;
@nums = split / /, $in, 3;
$what = shift @nums;
shift @nums;
$rest = shift @nums;
$rest = " ".$rest." ";
$sum = () = $rest =~ /(?<=\s)$what(?=\s)/g;
print $sum;
print "\n";
}
2
#!/usr/bin/env perl
while (<>) {
$in = $_;
@nums = split / /, $in, 3;
$what = shift @nums;
shift @nums;
$rest = shift @nums;
$rest = " ".$rest." ";
if(!$reg{$what}){
$reg{$what} = qr/(?<=\s)$what(?=\s)/;
}
$sum = () = $rest =~ /$reg{$what}/g;
print $sum;
print "\n";
}
我也尝试过暴力方法,哈希表,grep ...所有超出给定的时间限制,我不知道如何编写任何比上面两个更快的工作。有什么想法吗?
编辑:摆脱复制列表后(原来数字也可以是负数):
#!/usr/bin/env perl
while ($line = <>) {
$line =~ s/^(-?\d+) \d+//;
$what = $1;
$sum = () = $line =~ / $what\b/g;
print $sum;
print "\n";
}
edit2 :通过http://www.chengfu.net/2005/10/count-occurrences-perl/:
print $sum = (($line =~ s/ $1\b//g)+0);
导致代码比以下快2倍:
print $sum = () = $line =~ / $1\b/g;
立即行动,谢谢:)
答案 0 :(得分:3)
首先,你正在进行大量的复制。我在第一个例子中每次复制一个大字符串时都标记了:
while (<>) {
$in = $_; # COPY
@nums = split / /, $in, 3; # COPY
$what = shift @nums;
shift @nums;
$rest = shift @nums; # COPY
$rest = " ".$rest." "; # COPY
$sum = () = $rest =~ /(?<=\s)$what(?=\s)/g;
print $sum;
print "\n";
}
为了加快速度,请避免使用副本。例如,使用while ($in = <>)
(或只是跳过$in
并使用$_
)。
为了提取$what
和计数,我想我会尝试这而不是split
:
$in =~ s/^(\d+) \d+//;
$what = $1;
不要在前后添加空格,只需使用\b
代替\s
的外观。
$sum = () = $in =~ /\b$what\b/g;