所以,我今天探索了www.hackerearth.com并在ruby中解决了我的第一个问题陈述:http://www.hackerearth.com/problem/algorithm/palindrome-count-1/
回文数问题:
给定一个字符串S,计算作为回文的非空子字符串的数量。 子字符串是字符串中任何连续的字符序列。 如果字符串的反向与自身相同,则称字符串为回文。 如果它们出现在S
中的不同位置,则两个子字符串是不同的输入:输入只包含一行包含字符串S的行。
输出:打印单个数字,即回文子字符串的数量。
约束
1< = | S | < = 50
S仅包含小写拉丁字母,即字符a到z。
示例输入(明文链接):dskjkd
示例输出(明文链接):7
说明 -
7个子字符串是d,s,k,j,k,d,kjk。
时限3秒(s)
内存限制256 MB
来源限制1024 KB
以下是我的所作所为:
chars = gets.chomp.gsub(' ', '').split('')
counts = chars.count
(2..chars.count).each do |len|
chars.combination(len).each do |comb|
string = comb.inject(:<<)
counts += 1 if string.reverse == string
end
end
puts counts
然而,就时间执行和内存使用而言,这种方法似乎效率低下。有没有办法优化这个?或者对此解决方案有任何其他方法,也欢迎算法作为解决方案!感谢。
修改
因为,所有答案都是正确的。我必须选择一个有效的。所以,我运行了基准测试,结果如下:https://gist.github.com/suryart/7577481
根据结果,您可以看到this answer更快。感谢您的新方法/解决方案! :)
答案 0 :(得分:2)
这种方法 - 伪代码 - 应该可行。
input: String s
// each single letter is palindrome itself
palindromsCount = length(s)
// let count all odd-length palindromes first (palindrome of length 1 already counted)
// we will be checking from the very middle of a sub-string, if it is symmetric
for(int i = 1; i < length(s)-1; i++)
for(int j = 1; ; j++)
if (i - j < 0 || i + j >= length(s) || s[i-j] != s[i+j])
break
else
palindromsCount += 1
// let count in similar way all even-length palindromes
for(int i = 0; i < length(s)-1; i++)
for(int j = 0; ; j++)
if (i - j < 0 || i + j + 1 >= length(s) || s[i-j] != s[i+j+1])
break
else
palindromsCount += 1
编辑当然,这两个循环可以组合成一个循环 - 我不想这样做是为了提高可读性。
答案 1 :(得分:1)
使用该算法从What is the best way to split a string to get all the substrings by Ruby?
获取字符串的所有子集count = 0
(0..len-1).each do |i|
(i..len-1).each do |j|
temp = s[i..j]
count = count + 1 if temp == temp.reverse
end
end
puts "found #{count} palindromes"
答案 2 :(得分:1)
Enumerable#each_cons在这里很方便:
str = "momanddadpaddledthekayak"
b = str.chars
(1..b.size).reduce(0) {|t,n| t + b.each_cons(n).reduce(0) \
{|r,e| w = e.join; w==w.reverse ? r + 1 : r}} # => 30
如果我们想看到苍白的景象:
b = str.chars
pals = (1..b.size).each_with_object([]) {|n, a| b.each_cons(n).each \
{|e| w = e.join; a << w if w==w.reverse}}
p pals.size # => 30
p pals # => ["m", "o", "m", "a", "n", "d", "d", "a", "d", "p", "a",\
"d", "d", "l", "e", "d", "t", "h", "e", "k", "a", "y",
"a", "k", "dd", "dd", "mom", "dad", "aya", "kayak"]
编辑:@squiguy做了有用的观察,我们可能不想计算重复数。如果是这种情况,我上面的第一个计算就无法使用,第二个计算必须改变为squiguy暗示(例如p a.uniq.size
)或更改为构建散列而不是数组:
b = str.chars
pals = (1..b.size).each_with_object({}) {|n,h| b.each_cons(n).each \
{|e| w = e.join; h[w] = 0 if w==w.reverse}}.keys
p pals.size # => 17
p pals# => ["m", "o", "a", "n", "d", "p", "l", "e", "t",\
"h", "k", "y", "dd", "mom", "dad", "aya", "kayak"]
[修改:将each
替换为each_with_object
。在重读这个问题时,似乎要计算重复数。]