丑数是质因数仅含2、3、5的正整数(1亦算),判断需不断除尽2、3、5,最终结果必须为1;若中途余数含其他质因数(如14÷2=7),则不是丑数。

什么是丑数,以及为什么不能只除2、3、5一次
丑数是指正整数中质因数只包含 2、3、5 的数(1 也被定义为丑数)。常见误区是:看到能被 2、3 或 5 整除,就认为是丑数。但比如 14 能被 2 整除,剩下 7 —— 而 7 不在 {2,3,5} 中,所以不是丑数。
核心逻辑是:不断用 2、3、5 去除尽这个数,最后结果必须恰好等于 1 才算丑数。
- 对
n 直接返回 <code>false(丑数定义要求是正整数) -
n == 1是边界情况,直接返回true - 只要
n还能被2整除,就持续除以2;同理处理3和5 - 最后检查剩余值是否为
1
标准实现:循环除尽法(推荐)
这是最直观、不易出错的写法,时间复杂度 O(log n),空间 O(1),且兼容所有 C++ 标准(包括 C++11 及以后)。
bool isUgly(int n) {
if (n
<p>注意点:</p><div class="aritcle_card flexRow artxards">
<div class="artcardd flexRow">
<a class="aritcle_card_img" rel="nofollow" href="/xiazai/gongju/2823" title="C++14"><img
src="https://img.php.cn/upload/manual/001/431/639/6ac8b33c327c4749.png" alt="C++14" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
<div class="aritcle_card_info flexColumn">
<a rel="nofollow" href="/xiazai/gongju/2823" title="C++14" class="overflowclass">C++14</a>
<p class="overflowclass">C++14 对 C++11 的修正与增强版本,适合旧系统维护和较老工具链兼容。</p>
</div>
<a rel="nofollow" href="/xiazai/gongju/2823" title="C++14" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span>
</a>
</div>
</div>
- 使用
for (int p : {2, 3, 5})避免重复写三段 while,也防止漏掉某个因子 -
while (n % p == 0)确保“除尽”,不是只除一次 - 不要用
float或double做整除判断——浮点精度会导致14 / 2 == 7.0判断失败
递归写法容易踩的坑
有人倾向写成递归形式,比如 return n == 1 || (n % 2 == 0 && isUgly(n/2)) || ...,但这有明显问题:
- 没处理
n 会无限递归(如 <code>isUgly(0)→isUgly(0)) - 短路逻辑不保证顺序,某些编译器可能先算后面分支,导致除零或负数递归
- 栈深度随 log n 增长,对极大数(如接近
INT_MAX)有风险 - 可读性反而不如循环清晰
除非明确要求函数式风格且已加完备守卫,否则不建议递归。
LeetCode 测试用例里容易忽略的细节
LeetCode 第 263 题(Ugly Number)的测试用例包含几个易错点:
-
isUgly(0)返回false—— 0 不是正整数 -
isUgly(-2147483648)(即INT_MIN)传入时,若函数参数是int,值不变,但后续n % 2在负数下仍可计算(C++ 中负数取模符号取决于实现,但n % 2 == 0对偶数仍成立);不过更稳妥做法是开头就判n -
isUgly(1)必须返回true,这是定义,不是特例 - 如果用
long long接参再转回int,反而引入不必要转换,无意义
真正需要小心的,是把“能被 2/3/5 整除”和“质因数仅含 2/3/5”混为一谈——前者是必要不充分条件。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










