[英]How can I improve the performance of this small Ruby function?
我目前正在执行 Ruby 质询,并且对于某些字符串输入很长(10.000+ 个字符)的测试用例, Terminated due to timeout
出现错误。
如何改进我的代码?
给您一个仅包含字符 A 和 B 的字符串。 您的任务是将其更改为没有匹配的相邻字符的字符串。 为此,您可以删除字符串中的零个或多个字符。
您的任务是找到所需删除的最少数量。
例如,给定字符串s = AABAAB
,删除位置0
和3
的A
以使s = ABAB
删除2
。
def alternatingCharacters(s)
counter = 0
s.chars.each_with_index { |char, idx| counter += 1 if s.chars[idx + 1] == char }
return counter
end
谢谢!
这可能会更快地返回计数:
str.size - str.chars.chunk_while{ |a, b| a == b }.to_a.size
第二部分将String#chars方法与Enumerable#chunk_while结合使用。 这样第二部分在子数组中分组:
'aababbabbaab'.chars.chunk_while{ |a, b| a == b}.to_a
#=> [["a", "a"], ["b"], ["a"], ["b", "b"], ["a"], ["b", "b"], ["a", "a"], ["b"]]
如果可以使用,则squeeze
:
str.length - str.squeeze.length
否则,您可以尝试匹配前面有另一个A
(或B
)的那些A
(或B
)的正则表达式:
str.enum_for(:scan, /(?<=A)A|(?<=B)B/).count
使用enum_for
可以避免创建中间数组。
主要问题:
s.chars.each_with_index { |char, idx| counter += 1 if s.chars[idx + 1] == char }
是您不将chars
保存到变量中的事实。 s.chars
会将字符串撕成一个字符数组。 循环外的第一个s.chars
调用很好。 但是,没有理由对s
中的每个字符都这样做。 这意味着如果您有一个 10.000 个字符的字符串,您将实例化大小为 10.000 的 10.001 arrays。
重新使用字符数组会给你带来巨大的性能提升:
require 'benchmark'
s = ''
options = %w[A B]
10_000.times { s << options.sample }
Benchmark.bm do |x|
x.report do
counter = 0
s.chars.each_with_index { |char, idx| counter += 1 if s.chars[idx + 1] == char }
# create a character array for each iteration ^
end
x.report do
counter = 0
chars = s.chars # <- only create a character array once
chars.each_with_index { |char, idx| counter += 1 if chars[idx + 1] == char }
end
end
user system total real
8.279767 0.000001 8.279768 ( 8.279655)
0.002188 0.000003 0.002191 ( 0.002191)
您还可以使用each_cons
和count
之类的枚举器方法来简化代码,这不会大大增加性能成本,但会使代码更具可读性。
Benchmark.bm do |x|
x.report do
counter = 0
chars = s.chars
chars.each_with_index { |char, idx| counter += 1 if chars[idx + 1] == char }
end
x.report do
s.each_char.each_cons(2).count { |a, b| a == b }
# ^ using each_char instead of chars to avoid
# instantiating a character array
end
end
user system total real
0.002923 0.000000 0.002923 ( 0.002920)
0.003995 0.000000 0.003995 ( 0.003994)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.