LeetCode 202. 快乐数(练练hash链表)

序言

题目用常规方法去做思路还是挺简单的,我想了半天的数学方法,没想出来个所以然,官方题解还给出了快慢指针,但是我觉得还是hash好用。有不足之处希望大家在留言区指正。
LeetCode 202. 快乐数(练练hash链表)_第1张图片

题目描述

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

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

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

示例:

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

思路分析

对于一个数猜想可能有三种情况
1.最终回到1
2.最终陷入循环
3.最终趋向于无穷大
这里主要还是讨论2和3的可能性

情况三分析

当数是三位数时,下一个数=个位2+十位2+百位2,三位数最大值999的下一个是243,所以任何一个三位数的下一个数都是三位数以内。
所以情况三不成立。

算法分析

最终我们可以将题目简化为判断环是否存在的问题。判断环可以hash和快慢指针,这题用hash比较好,但是我两种都分析一下吧。
hash:
创建一个hash表,将产生的数不停的放进去,如果发现有相同的数了,则说明存在环。
快慢指针:
用slow和quick存放开始的数,然后每次操作后更新slow=n,每两次操作后更新quick=n,这样如果存在环,则slow和quick在有限次操作后一定会相等。
操作次数可以用同余方程来算(我列出来不会解)(狗头):
(k-(m-n))%n=(2k-(m-n))%n (k是循环次数)
LeetCode 202. 快乐数(练练hash链表)_第2张图片

代码(只有hash方法)

主要是我懒,快慢指针思路比较简单,看一下算法分析应该就会了。

typedef struct node{
    int data;
    struct node *next;
}element;
int inHash(element *hash,int n){
    element *p;
    p=hash[n%10].next;
    while(p!=NULL){
        if(p->data==n)
            return 1;
        p=p->next;
    }
    p=(element*)malloc(sizeof(element));//解决冲突我一直喜欢用链表,个人爱好
    p->data=n;
    p->next=hash[n%10].next;
    hash[n%10].next=p;
    return 0;
}
bool isHappy(int n){
    int start=0,data=0,flag;
    element hash[10];
    for(int i=0;i<10;i++)
        hash[i].next=NULL;
    flag=inHash(hash,n);//判断是否构成环
    while(n!=1){
        data=0;
        while(n!=0){
            data=pow(n%10,2)+data;
            n/=10;
        }
        flag=inHash(hash,data);//返回1构成环,返回0不构成
        if(flag)
            return false;
        n=data;
    }
    return true;
}

时间复杂度不会分析,应该是O(1到n之间,应该有数学式可以推导,但是我不会,有会的dalao可以在评论区写一下,我也学习一下)

你可能感兴趣的:(数据结构,leetcode,算法,哈希)