202、快乐数;258、各位相加;自然数的各位和以及各位平方和,链表有环的判定。

202、快乐数

编写一个算法来判断一个数 n 是不是快乐数。
「快乐数」定义为:对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和,然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。如果 可以变为 1,那么这个数就是快乐数。
如果 n 是快乐数就返回 True ;不是,则返回 False 。

输入:19
输出:true
解释:
12 + 92 = 82
82 + 22 = 68
62 + 82 = 100
12 + 02 + 02 = 1

**解答:**首先考虑暴力法,即利用一个函数求取数字的各为平方和,然后用该结果直接递归,判定最终结果是否为1。结果显而易见,必会超时,大概率因此数字的平方和陷入了一个环中。
对题目进行分析总结,数字的平方和具有以下特征:
1、1的平方和一直为1,等同于一个只有元素1的环。
2、1位数的最大平方和位81;2位数的最大平方和位:162;三位数的最大平方和为:24;4位数的最大平方和为:324;5位数的最大平方和为:405; 32位数的最大平方和为:32*81=2592。而大于4为数的平方和再进行一轮平方和必然会损失一位数,一直降到3位数以下。
因此:一个数进行一直平方和只有两种结果:1)陷入为1的环,即返回True;2)陷入一个不含1的环,然后一直在环中循环。
针对上述结论:解题思路有:1)利用set集合保存已经出现过的n,当再次出现n时推出循环,并判断n是否为1。2)利用链表中解决有环的方法,采用快慢指针进行解决。循环终止条件为:

def isHappy(self, n: int) -> bool:
        def get_square_add(n):
            count = 0 
            while n>0:
                count += (n%10)**2
                n //= 10#特别注意。python //表示整数,是一个整数。 /是直除,是一个浮点数。使用/会一直循环。
            return count
        # solution1:利用set进行是否有环。
        # seen = set()
        # while n !=1 and n not in seen:
        #     seen.add(n)
        #     n = get_square_add(n)
        # return n==1
        # solution2、 利用快慢指针判断是否有环
        slow = n
        fast = get_square_add(n) #注意不能初始化也为n,不然会直接slow==fast,进不去循环
        while slow !=fast and fast != 1: #由于1的平方和还为1,因此只需要判断是否fast为1即可,如果要先到达,肯定是fast先。或者干脆不用判断即可。因此最终会落入到1的环中。
            slow = get_square_add(slow)
            fast = get_square_add(get_square_add(fast))
        return fast ==1

**易错点:**1)求各平方和时:python //表示整数,是一个整数。 /是直除,是一个浮点数。由于小数的原因,使用/会一直循环。
2)快慢指针循环终止条件:可以为while slow !=fast and fast != 1 and slow!=1。但是鉴于如果有1,则会进入1的循环,且不会跳出。因此可直接判断fast这个快指针即可。或者两者都不用判断,最后循环结束时判断其中一个是否为1即可。
3)slow和fast的初始化一个为n,一个为get(n)。如果都设置为n,则会直接跳出循环。

上述求了一个数的各位平方和,下面求一个数的各位和的方法

258. 各位相加

给定一个非负整数 num,反复将各个位上的数字相加,直到结果为一位数。
输入: 38
输出: 2
解释: 各位相加的过程为:3 + 8 = 11, 1 + 1 = 2。 由于 2 是一位数,所以返回 2。
进阶:
你可以不使用循环或者递归,且在 O(1) 时间复杂度内解决这个问题吗?

理解: 一个3位数可表示未:x100+10y+z =99x+9y+x+y+z。因此,求x100+10y+z的系数之和即x+y+z等同于针对99x+9y+x+y+z求x+y+z;那么可以99x+9y+x+y+z对9求余,即得x+y+z,此时x+y+z必然小于9,不需要再求各位之和了。同时:为了避免为9时得为0,采用(a-1)%9+1的方式对9求余。

def addDigits(self, num: int) -> int:
        if num ==0:
            return 0
        #1、直观想法,使用递归暴力破解
        # if num<10:
        #     return num
        # #求取数字的各位之和
        # sum =0
        # sum += while(...)
        # addDigits(sum)
        #2、数学推导的方法
        # x*100+10*y+z =99*x+9*y+x+y+z。因此,求x*100+10*y+z的系数之和即x+y+z等同于针对99*x+9*y+x+y+z求x+y+z
        #那么可以99*x+9*y+x+y+z对9求余,即得x+y+z。为了避免为9时得为0,采用(a-1)%9+1的方式对9求余
        return (num-1)%9+1
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值