LeetCode 202.快乐数

题目描述

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

「快乐数」 定义为:

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

如果 n快乐数 就返回 true ;不是,则返回 false

示例 1:

输入:n = 19
输出:true
解释:
1^2 + 9^2 = 82
8^2 + 2^2 = 68
6^2 + 8^2 = 100
1^2 + 0^2 + 0^2 = 1

示例 2:

输入:n = 2
输出:false

提示:

  • 1 <= n <= 231 - 1

题解

方法一:哈希表

时空复杂度: O(243⋅3+logn+loglogn+logloglogn)… = O(log⁡n) O(logn)

这里的时空复杂度分析有些复杂,这里贴出官方的分析,大家可以参考[202.快乐数](202. 快乐数 - 力扣(LeetCode))

这题根据题意可以直接进行模拟,然后将出现过的数存入Set集合中,在模拟过程中如果出现了在Set集合中存在的数字,则可以判断不是快乐数,当n等于1的时候就代表为快乐数字,这题时间复杂度笔者不会分析(泪目)。

代码:

public boolean hashMethod(int n) {
	//创建集合存储出现过的元素
    Set<Integer> set = new HashSet();
    //当n不等于1的时候
    while(n != 1) {
        //加入当前数字进入集合中	
        set.add(n);
        //创建变量统计总和
        int sum = 0;
        while(n != 0) {
            sum += Math.pow((n % 10),2);
            n /= 10;
        }
        //判断当前数字是否在集合中出现过
        if(set.contains(sum)) {
            return false;
        }
        //改变n
        n = sum;
    }
    //返回true
    return true;
}

方法二:快慢指针

时空复杂度: O(logn) O(1)

这里我们可以参考判圈的算法,虽然我们这里是对数字的处理,但是我们也可以类比到链表结构的前后节点,如果我们使用了判圈算法,可以省去存储遍历过的节点的Set集合的空间。具体思想就是创建一个快指针,一个慢指针,快指针一次移动两个单位,慢指针一次移动一个单位,这样子如果当有环出现的时候,快指针在环内就能追上慢指针了。

代码:

public boolean isHappy(int n) {
    //定义快慢指针
    int slow = n;
    int fast = getNext(n);
    //当快指针不为1并且快慢指针不相等的时候继续循环
    while(fast != 1 && slow != fast){
        slow = getNext(slow);
        fast = getNext(getNext(fast));
    }
    //判断快指针是否等于1,即是否为快乐数,或者两个指针在环中相遇了
    return fast == 1;
}

public int getNext(int n) {
    //定义求和变量
    int sum = 0;
    while(n != 0) {
        sum += Math.pow((n % 10),2);
        n /= 10;
    }
    return sum;
 }

总结

这道题目考察了我们,模拟,选用合适的数据结构存储数据的能力,这里我们合适使用Set集合存储,因为,Set中查找元素只需要O(1)的时间复杂度,而链式结构需要O(n)。方法二的快慢指针适用于查找存在环形结构的题目。好了,本题的就说到这里!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

墨白Coding

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值