编写一个算法来判断一个数 n 是不是快乐数。
「快乐数」定义为:对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和,然后重复这个过程直到这个数变为 1,也可能是无限循环但始终变不到 1。如果 可以变为 1,那么这个数就是快乐数。如果 n 是快乐数就返回 True ;不是,则返回 False 。
示例:
输入:19
输出:true
解释:
1^2+9^2 = 82
8^2+2^2 = 68
6^2+8^2 = 100
1^2+0^2+0^2 = 1
首先分析一下题干,什么是快乐数?给你一个数,该数的各个位置上(个、十、百……)数的平方之和,再对该数各个位置上的数求平方和,不停重复这一步骤,直到某次的平方和为1,则说明一开始给的数为快乐数。
但你不能简单的设置一个循环,让该数一直重复该步骤。因为万一在某次循环中的和与之前某次和一样,那么就会陷入一个无限循环。所以我们在撰写代码时,要设定一个条件,判断该次循环求出的和有没有与之前的某次和重复,如果重复则return False;如果不重复就继续循环。具体思路如《代码随想录》所示。
完整代码如下:
class Solution:
def isHappy(self, n: int) -> bool:
record = set()
while True:
n = self.get_sum(n)
if n == 1:
return True
# 如果中间结果重复出现,说明陷入死循环了,该数不是快乐数
if n in record:
return False
else:
record.add(n)
def get_sum(self,n: int) -> int:
new_num = 0
while n:
n, r = divmod(n, 10)
new_num += r ** 2
return new_num
首先,设计一个空集合record用来储存每次生成的和。只要没有重复,循环便一直存在。n = self.get_sum(n)的意思是将n的各个位置上的平方和赋值给新的n,判断新的n是否等于1,如是则return True;如果新的n在record中存在(即代表之前的和中出现过这个数),则return False;如果n既不等于1,也不存在于record中,则在record中加入这个n的值。
在上述代码中设计了一个求数n各个位置上平方和的函数get_sum,以下代码是对该函数的设计。
def get_sum(self,n: int) -> int:
new_num = 0
while n:
n, r = divmod(n, 10)
new_num += r ** 2
return new_num
首先,将0赋值给new_num为初始值,接着进入循环(只要n还存在)。n, r = divmod(n, 10)是指求出新的n值和r值,divmod(n, 10)的意思是求出n/10的商和余数。以19为例,那么第一次循环中,19/10 = 1……9,那么新的n为1,r为9,new_num就等于9*9=81,此时n=1还存在,那么继续循环,1/10 = 0……1,new_num = 81+1*1=82,此时n=0,循坏结束。则得到第一次数的平方和为82。
根据上述思路编写的代码便可以完成题干的要求。