同题上一篇:基于集合的方案
题目描述
编写一个算法来判断一个数 n 是不是快乐数。
「快乐数」 定义为:
对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。
然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。
如果这个过程 结果为 1,那么这个数就是快乐数。
如果 n 是 快乐数 就返回 true ;不是,则返回 false 。
思路与算法
代码
class Solution:
def isHappy(self, n: int) -> bool:
# 计算n的每位数字的平方和
def next_num(n:int) -> int:
return sum(int(digit)**2 for digit in str(n))
slow = fast = n
# 如果快慢指针相遇,说明形成环
while fast != 1:
slow = next_num(slow)
fast = next_num(next_num(fast))
if slow == fast:
return fast == 1
return True
总结
- 使用两个指针(或称快慢指针)同时在序列中移动。慢指针一次移动一步,而快指针一次移动两步。如果序列中存在循环,则快指针必然会在某个时刻追上慢指针(套圈);如果没有循环,快指针会先到达终点。
- 使用快慢指针(Floyd 判圈算法)不需要额外空间,适用于检测链表循环等场景,也是判断无限循环的常见技巧。
- 在使用 Floyd 判圈算法时,为防止初始状态下快慢指针相同而产生误判,可以采用两种常见方法:
- 初始化时让快指针先走一步:将快指针设置为 head.next,从而保证初始时快慢指针不在同一位置,但需要注意边界条件(例如链表为空或只有一个节点的情况)。
- 从同一起点开始,但在循环内先移动再比较:快慢指针均从 head 开始,在每次循环中先更新指针位置(快指针走两步,慢指针走一步),再进行比较,这样可以避免初始时误判。