好久没来简书写东西了,账号都自动登出了。。(尴尬脸)。。
最近一直在刷Ruby Koans(安利脸),翻着镐头书(安利脸 ps:绝版了,不过有英文第三版),逛着stackoverflow,嗯,这就是生活。
废话不多说,看题:
Write a program that outputs the string representation of numbers from 1 to n.
But for multiples of three it should output “Fizz” instead of the number and for the multiples of five output “Buzz”. For numbers which are multiples of both three and five output “FizzBuzz”.
Example:
n = 15,
Return:
[
"1",
"2",
"Fizz",
"4",
"Buzz",
"Fizz",
"7",
"8",
"Fizz",
"Buzz",
"11",
"Fizz",
"13",
"14",
"FizzBuzz"
]
分析
题目很简单,生成一个字符串数字数组,其中3和5的倍数被相应字符串替换。那就一步一步来吧:
- 生成一个字符串数字数组:
datas=("1"..n.to_s).to_a
("1"..n.to_s)
是生成一个从"1"
到"n"
的Range
,然后调用to_a
方法转换成Array
- 将数组中3的倍数用字符串“Fizz”替换:
(2.. datas.size()-1).step(3).each do |i|
datas[i]="Fizz"
end
(2.. datas.size()-1).step(3)
以3为间隔生成一个Range
,用作datas
中索引3的倍数的元素,在block中修改这些元素的值为“Fizz”
- 将数组中5的倍数用字符串“Buzz”替换:
(4.. datas.size()-1).step(5).each do |i|
datas[i]= "Buzz"
end
- 将数组中15的倍数用字符串“FizzBuzz”替换:
(14.. datas.size()-1).step(15).each do |i|
datas[i]= "FizzBuzz"
end
最后,整体源码如下:
# @param {Integer} n
# @return {String[]}
def fizz_buzz(n)
datas=("1"..n.to_s).to_a
(2.. datas.size()-1).step(3).each do |i|
datas[i]="Fizz"
end
(4.. datas.size()-1).step(5).each do |i|
datas[i]= "Buzz"
end
(14.. datas.size()-1).step(15).each do |i|
datas[i]= "FizzBuzz"
end
return datas
end
备注
刚开始接触这个题下意识以为是考察如何替代求余运算来提高效率。。。too young啊,又掉进c坑里去了。
所以说,有没有更高效率的写法,有,看看Runtime Distribution就知道有,可是真的需要么?刚开始我用C++实现就一直在考虑效率,轻松跑到4ms左右又换成golang来写,同样的优化方法(利用三次循环减少条件判断而不是一次循环多次判断,当n非常大的时候减少条件判断意味着减少分支预测,也就意味着性能提升),结果却不是那么明显。也许,leetcode的测试用例太少了;也许,高级语言本身的损耗高于代码结构带来的损耗;也许,我的某一次提交运行的时候,机器正在生孩子负载太重了。太多的也许,让我想起镐头书里孟岩在推荐序中的一句话:
面对执行性能与开发效率的谜题,Ruby毫不犹豫的选择了开发效率,选择了对人脑友好
所以,我不打算继续纠结于性能(´▽`)