leetcode题目——Happy Number

题目:

编写一个算法来判断一个数 n 是不是快乐数。

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

如果 n 是快乐数就返回 True ;不是,则返回 False 。

在这里插入图片描述

第一步:需要将每一位的数字单独拿出来求平方

整数最大为10位数,但用1000000000*10之后就无法运行,所以会报错,那么添加一个计数器k,最终k为11但终止循环,导致m不会再增加。

bool isHappy(int n){
    n = 375231;
    int r = 0;
    int m = 1;
    for (int k = 1; k <= 10; k++){
        int d = n / m % 10;//d: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
                           //m: 1, 10, 100, ..., 1000000000
                           //k: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
        printf("%d\n",d);
        r += d * d;
        if (k < 10){
            m *= 10; 
        }
     }
     return false;
}

另一种想法是倒过来做,这样输出的位数是从高位到低位

bool isHappy(int n){
    int r = 0;
    int m = 1;
    for (int m = 1000000000; m >= 1; m /= 10){
        int d = n / m % 10;
        r += d * d;
        }
     }
     printf("%d\n",r);
     return false;
}

简化写法(不断将原本的数字/10)

bool isHappy(int n){
    int r = 0;
    while (n != 0){
       int d = n % 10;
       n /= 10;
       r += d * d;
     }
     printf("%d\n",r);
     return false;
}
第二步:对其进行循环
int next_n(n){
    int r = 0;
    while (n != 0){
       int d = n % 10;
       n /= 10;
       r += d * d;
     }
     return r;
}
bool isHappy(int n){
    printf("%d\n",next_n(n));
    return false;
}

我们需要知道,程序做到什么时候才停止,检查数字n是否出现过,当他没有出现过,一直走,当n再次出现时有两种情况,①n为1,此事是happy number ②n不会1,则为false。

int next_n(n){ //回传下一次的n
    int r = 0;
    while (n != 0){
       int d = n % 10;
       n /= 10;
       r += d * d;
     }
     return r;
}
bool contain(int* history, int size, int n){ //检查 n 是否在 history 中出现过
     for (int i =0; i < size; i++){
        if (history[i] == n){
           return true;
        }
     }
     return false;  //false的意思就是它没有出现过
}
bool isHappy(int n){
    int history[10000]; // 我们去过哪里
    int size = 0;  //总共有几个地方
    //history = [?,?,?,?,?,?]
    //size = 0
    
    // n = 19
    while (!contain(history, size, n)){
          history[size] = n; //histort[0]=19
          size++;
          n = next_n(n);  // n : 82
    }
    return n == 1;
}
疑问:有没有可能产生的新的数字超过一万个?

想想如果有10位数,每位数均为最大,9999999999 ==》 9 * 9 * 10 =810
他运算的数字最大为810
我们可以在循环前第一次先无条件走一步,此时次数最多就只有810种不一样。
但是确定空间大小仍是不确定的,所以可以让其变循环,空间逐渐长大

龟兔赛跑算法(Floyd’s Tortois and Here)

在这里插入图片描述
一开始都在起点,乌龟一次走一步,兔子一次走两步,兔子会从尾巴上追上乌龟并且撞在一起,此时便说明会有循环发生,对于此题,我们需要检查当两者撞在一起时是否为1即可。

双指标方法:
int next_n(n){ //回传下一次的n
    int r = 0;
    while (n != 0){
       int d = n % 10;
       n /= 10;
       r += d * d;
     }
     return r;
}
bool isHappy(int n){
    int slow = n;
    int fast = n;
    do{                     //一开始两个是在一起的
       slow = next_n(slow); //乌龟走一步
       fast = next_n(next_n(fast));//兔子走两步
    } while (slow != fast);  //走完之后就要检查两个是否撞在一起,当不一样时,继续做
    return fast == 1; // 检查乌龟和兔子都可以
}

不需要额外的阵列占用空间。

class Solution:
    def getNext(self, n: int) -> int:
        next_n = 0
        while(n != 0):
            next_n += (n % 10) ** 2
            n = n // 10
        return next_n

    def isHappy(self, n: int) -> bool:
        slow = n
        fast = self.getNext(n)
        while(fast != 1 and slow != fast):
            slow = self.getNext(slow)
            fast = self.getNext(self.getNext(fast))
        return fast == 1

作者:coldme-2
链接:https://leetcode-cn.com/problems/happy-number/solution/hashsetshuang-zhi-zhen-python-by-coldme-2/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值