FizzBuzz
在计数游戏 FizzBuzz 中,玩家从 1 开始数数,并用单词替换某些数字。给定回合编号 n,返回玩家在该回合说的内容:如果 n 同时能被 3 和 5 整除,则返回 "FizzBuzz";如果 n 只能被 3 整除,则返回 "Fizz";如果 n 只能被 5 整除,则返回 "Buzz";否则,返回以字符串形式表示的 n 本身,例如 "7"。
函数
- ninteger
- 回合编号,一个正整数
- 返回值string
- 第 n 轮说出的单词或数字,作为字符串
约束条件
1 ≤ n ≤ 109- 答案始终是一个字符串,即使它本身是数字也是如此。
示例
- 输入
- n = 15
- 输出
- "FizzBuzz"
- 解释
- 15 除以 3 等于 5,15 除以 5 等于 3,两者余数都为 0,所以第 15 轮是
"FizzBuzz"。
- 输入
- n = 7
- 输出
- "7"
- 解释
- 7 除以 3 余 1,除以 5 余 2,因此没有词语适用,你要将这个数字作为文本返回,即
"7"。
进阶
新规则规定,7 的倍数输出 "Bazz",并按顺序拼接单词,所以 105 输出 "FizzBuzzBazz"。怎样添加这条规则,而不必为每种组合都编写一个分支?
提示
逐个打开提示,每个都会多透露一点。
取余运算符可以告诉你一个数能否被另一个数整除:当
n除以 3 的余数为 0 时,n恰好能被 3 整除。想想 15。它能被 3 和 5 整除。你应该先运行哪个检查,才能让 15 得到
"FizzBuzz",而不是"Fizz"?先测试是否能被 15 整除,然后测试是否能被 3 整除,最后测试是否能被 5 整除。如果都不匹配,就把数字转换为字符串。确保转换后写出每一位数字,这样 10^9 会得到
"1000000000",而不是科学计数法。
题解
每条规则都是一次余数检查。关键陷阱在于顺序:15 能被 3 整除,所以如果函数先检查 3 并立即返回,遇到 15 时就会返回 "Fizz"。你可以先检查组合情况,也可以根据两次检查的结果构建答案。
根据两项检查构建单词
思路
从一个空字符串开始。如果 n 能被 3 整除,就添加 "Fizz";如果 n 能被 5 整除,就添加 "Buzz"。这两个检查总是会运行,因此 15 的倍数会按顺序收集这两部分,并变成 "FizzBuzz",无需特殊处理。如果字符串仍为空,就表示两个规则都不适用,此时返回一个字符串形式的数字。
算法
- 将
word设为空字符串。 - 如果
n % 3 == 0,追加"Fizz"。 - 如果
n % 5 == 0,追加"Buzz"。 - 如果
word为空,则将n转换为字符串后返回。 - 否则返回
word。
def fizzBuzz(n):
word = ""
if n % 3 == 0:
word += "Fizz"
if n % 5 == 0:
word += "Buzz"
# An empty word means neither 3 nor 5 divides n.
if word == "":
return str(n)
return word先检查 15,再检查 3,然后检查 5
思路
同时能被 3 和 5 整除的数,恰好就是能被 15 整除的数,因为 3 和 5 没有公因数。因此,合并后的规则只需检查一次:n % 15 == 0,并且要先检查。检查不通过后,匹配 3 表示只匹配 3,匹配 5 表示只匹配 5。每次检查都会立即返回;如果都不匹配,就将这个数作为字符串返回。
算法
- 如果
n % 15 == 0,返回"FizzBuzz"。 - 如果
n % 3 == 0,返回"Fizz"。 - 如果
n % 5 == 0,返回"Buzz"。 - 否则,将
n转换为字符串,并写出每一位数字。
def fizzBuzz(n):
if n % 15 == 0:
return "FizzBuzz"
if n % 3 == 0:
return "Fizz"
if n % 5 == 0:
return "Buzz"
return str(n)
易错点和边界情况
- 在检查 15 之前先检查 3 或 5,并立即返回:15、30 和 45 都会输出
"Fizz"。 - 返回数字而不是字符串。第 7 轮的结果是
"7"。 - 将大数字转换为科学计数法。在 R 中,直接转换会将 10^9 打印为
1e+09;请使用format(n, scientific = FALSE)。 - 打印答案,而不是返回答案。
常见问题3
为什么编程面试中会问 FizzBuzz?
它会检查你能否把一组简短规则转换成可运行的代码:取余测试、按正确顺序排列条件,以及使用正确的返回类型。对于经常编写代码的人来说,这只需几分钟,因此它适合作为更难问题之前的快速筛选。
你能不使用取模运算符解决 FizzBuzz 吗?
是的。用整数除法进行除法运算,再将商乘回去,并与 n 比较:只有没有余数时,两者才相等。打印整个序列时,你还可以使用两个计数器,分别在 3 和 5 时重置。
FizzBuzz 的时间复杂度是多少?
判断一个数字的答案是 O(1):固定次数的取余检查,以及将最多 10 位的数字转换为字符串。打印从 1 到 n 的序列需要 O(n)。
相似题目
运用相同思路的题目。做两三道,才能真正掌握一种模式。
def fizzBuzz(n):
# 在这里编写代码测试 #1
测试 #2
参数
n = 15
预期输出
"FizzBuzz"