⛅(day27)
目录
🖍题目:
题目分析:
解题思路:
✨解法一(规律总结)
🌈代码实现
🌟代码注释
✨解法二(递归直观解法)
🌈代码实现
🌟代码注释
🖍题目:
编写一个算法来判断一个数 n 是不是快乐数。
「快乐数」 定义为:
对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。
然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。
如果这个过程 结果为 1,那么这个数就是快乐数。
如果 n 是 快乐数 就返回 true ;不是,则返回 false 。
1 <= n <= 231 - 1
🌠示例 1:
输入:n = 19
输出:true
说明: += 82(第一次判断)
+
= 68(第二次判断,下面的一次类推为第几次判断)
+
= 100
+
+
= 1
🌠示例 2:
输入:n = 2
= 4
= 16
+
= 37
+
= 58
+
= 89
+
= 145
+
+
= 42
+
= 20
+
= 4
标记的这两部构成一个循环,所以2不是快乐数
输出:false
题目分析:
题目的要求就是判断所给的数是否符合“快乐数”的定义,这与水仙花数和回文数类似。都是判断所给的数据是否符合某种定义。
解题思路:
✨解法一(规律总结)
对于快乐数的定义,可经过有限的列举发现其中的规律。
那么我们有
所有不快乐数的数位平方和计算,最後都会进入 4 → 16 → 37 → 58 → 89 → 145 → 42 → 20 → 4 的循环中。
对此,当我们按照定义对快乐数进行判断时,只要再某一平方和计算后出现(4 → 16 → 37 → 58 → 89 → 145 → 42 → 20 → 4 )中的某一数字则会进入循环,那么即可判断这个数不是快乐数。
那么我们现在分析如何实现按定义进行平方和。
以n = 19为例,由定义每一次将该数替换为它每个位置上的数字的平方和
对此我们可以将n除于10后求余(取余符号%),那么就可以得到9
接着对n进行10的整除(整除符号%)那么就可以得到1
这时只需要对两步操作分别进行平方计算即可,+= 82。
🌈代码实现
def isHappy(n):
while True:
sqrsum = 0
while n > 0:
sqrsum += (n % 10) ** 2
n //= 10
if sqrsum == 1:
return True
elif sqrsum in [4, 16, 37, 58, 89, 145, 42, 20]:
return False
else:
n = sqrsum
🌟代码注释
def isHappy(n):
while True: # 主循环,用来按定义判断,不用规定循环结束条件
sqrsum = 0 # 初始化变量,用于储存计算结果和判断
while n > 0: # n最小值为零,当n=0时可省略,因为0的平方,整除,求余都为零
sqrsum += (n % 10) ** 2
n //= 10
# 第2层while循环结束表示对n的一次(第一,第二,第,,,次判断)判断结束
if sqrsum == 1: # 符合快乐数定义,返回True
return True
elif sqrsum in [4, 16, 37, 58, 89, 145, 42, 20]: # 不满足
return False
else:
n = sqrsum # 将前一次的判断的值赋给n,进行下一次判断
这一方法中的n=sqrsm类似于递归,可以理解成关于while循环的“递归”
✨解法二(递归直观解法)
上面规律总结法过于抽象,特别是对于(所有不快乐数的数位平方和计算,最後都会进入 4 → 16 → 37 → 58 → 89 → 145 → 42 → 20 → 4 的循环中。)这一结论,你只有遍历的数字得足够多才能得出这一规律。
下面我们介绍一个更加直观的解法。
我们直接按照定义遍历n,将n的每一个位数提出来进行平方和再相加。
但是我们知道数值n时不具有遍历这一属性的,不能直接去遍历n。
那我们要怎样才能遍历n?
我们可以使用str()函数把n转化位字符串,因为字符串具有遍历的属性。转换成字符串后我们就可以直接遍历n了。
但是字符串不能进行平方等操作,所以我们又需要使用int()函数将字符串转化成数值,这样就可以进行平方,求和等操作。
接着得到第一次判断的结果,那么我们只需用递归再次调用用于判断的函数再一次计算判断即可。
那么我们如何判断该数是否循环而不构成快乐数?
那么循环的特点是什么。
观察知道如果构成循环,那么必回在判断时的计算过程中出现重复的数字。
那么我们可以创建一个列表记录每一次判断产生的数值,如果为1即为快乐数。不为1则将其加入列表,如果下一次判断得出的数值已在列表中出现即为循环,不构成快乐数。
🌈代码实现
def isHappy(n):
def count(m):
global flag
lst.append(int(m))
result = 0
for i in range(len(m)):
result += int(m[i]) ** 2
if result == 1:
flag = 1
elif result in lst:
flag = 0
else:
count(str(result))
lst = []
m = str(n)
count(m)
return flag == 1
🌟代码注释
def isHappy(n):
def count(m): # m为字符串
global flag # 定义全局变量,确保在函数isHappy每一个处都能使用flag变量
lst.append(int(m)) # 将m转换为数值后
result = 0 # 初始化变量
for i in range(len(m)): # 遍历m
result += int(m[i]) ** 2 # 取出每一位数进行平方后求和
if result == 1: # 满足快乐数的定义
flag = 1 # 将标记值(变量)设为1
elif result in lst: # 判断计算出的数是否在列表内,是则不满足快乐数的定义
flag = 0 # 将标记值(变量)设为0
else:
count(str(result)) # 如果还未能判断是否为快乐数,用递归再次计算判断
lst = [] # 初始化用于储存每一次判断产生的数值
m = str(n) # 将n转换成字符串并赋给m
count(m) # 调用函数count
return flag == 1 # 如果flag的值为1则返回True,否则返回False
为什么要设置标志值flag呢?直接用return返回True或False不更简洁吗?
事实上,如果不使用标记值flag而直接实用return(如下代码所示),那么运行函数时是不会又任何返回值的
-----------------------------------
if result == 1:
return True
elif result in lst:
return False
今天就到这,明天见。🚀
❄❄❄❄❄❄❄❄❄❄❄❄❄❄❄❄❄❄❄❄end❄❄❄❄❄❄❄❄❄❄❄❄❄❄❄❄❄❄❄❄❄❄❄❄❄❄