快乐数

Leetcode 202.快乐数

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

快乐数」定义为:

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

示例 1:

输入:19
输出:true
解释:
12 + 92 = 82(这里的每个2代表平方的意思)
82 + 22 = 68
62 + 82 = 100
12 + 02 + 02 = 1
示例 2:

输入:n = 2
输出:false

提示:

1 <= n <= 231 - 1

首先我们要知道如何计算这个快乐数,

我们需要提取出这个数字的每一位然后进行平方和
提取每一位数字的操作为
d = n % 10;
n /= 10;
简单说就是除10取余
比如19 % 10 商1余9 这样就取出了19中的9,1同样的道理
n /= 10的作用是为了取出这个数字的每一位的值,例如19 / 10 = 1,将19中的十位数1取了出来
最后将这俩个数的平方和相加

int d = n % 10;
n /= 10;
 private int getNext(int n) {
        int sum = 0;
        while (n > 0) {
            int d = n % 10;
            n /= 10;
            sum += d * d; 
        }
        return sum;
    }

接下来我们就要判断在这个循环可不可以这个数变成1;
我们需要将每次循环的数字存储起来,方便我们查看在这个循环中是不是出现了相同的循环数,如果出现了相同的循环数,且这个数不是1,那么说明在这个循环里会出现一个有序循环,不可能变成1;
但是我们不能将所有的循环数都存储起来,然后去判断,那样会耗费大量时间和空间,所以在这里我们用到了HashSet;

科普一下(和这道题关系不大)
在HashSet中每天添加一个数字,他都会判断在这里面有没有这个数,如果有这个数,直接返回,有兴趣可以看看源代码

	 /** 
	 *Adds the specified element to this set if it is not already present.
     * More formally, adds the specified element <tt>e</tt> to this set if
     * this set contains no element <tt>e2</tt> such that
     * <tt>(e==null&nbsp;?&nbsp;e2==null&nbsp;:&nbsp;e.equals(e2))</tt>.
     * If this set already contains the element, the call leaves the set
     * unchanged and returns <tt>false</tt>.
     *
     * @param e element to be added to this set
     * @return <tt>true</tt> if this set did not already contain the specified
     * element
     */
    public boolean add(E e) {
        return map.put(e, PRESENT)==null;
    }

这句话的大概意思就是我上面所说的。

 class Solution {
    public boolean isHappy(int n) {
        Set<Integer> set = new HashSet<>();
        //在这里之所以会有!set.contains(n)这个条件是因为我需要
        //一个跳出条件,不然在一个数字中存在循环的话这个方法会一直执行下去
        while (n != 1 && !set.contains(n)) {
            set.add(n);
            //将添加在set中的数字继续进行getNext操作
            n = getNext(n);
        }
        return n == 1;
        
    }
    //计算出n的每个位置上数字的平方,然后求和
    private int getNext(int n) {
        int sum = 0;
        while (n > 0) {
            int d = n % 10;
            n /= 10;
            sum += d * d; 
        }
        return sum;
    }
}

2.双指针(快慢指针)

在方法一中我们说道,如果不是快乐数,会出现一个有序循环,就像下图一样
在这里插入图片描述
这样我们就可以设置俩个指针,一个快指针一个慢指针;
快指针每次走俩个单位,慢指针走一个单位,
如果是快乐数(存在有序循环),那么这俩个指针一定会在某个地方相遇,
如果不存在快乐数,快指针一定比慢指针先到达数字1.

在这里插入图片描述

在这里插入图片描述

如果存在有序循环,俩指针一定会在那个环里的某个位置相遇。

class Solution {
    public boolean isHappy(int n) {
       int slow = n;
       int fast = getNext(n);
       //第一个条件是为了一目了然,为了判断是否为1
       //第二个条件,判断是否相遇,如果相遇,则跳出循环
       //注意:不存在slow 和 fast 都等于1 且相遇的情况,因为fast比slow快,一定比slow先到达数字1
       while (fast != 1 && slow != fast) {
           slow = getNext(slow);
           fast = getNext(getNext(fast));
       }
       return fast == 1;
    }
    public int getNext(int n) {
        int sum = 0;
        while (n > 0) {
            int d = n % 10;
            n /= 10;
            sum += d * d; 
        }
        return sum;
    }
}

如有错误,请指教!

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值