LeetCode:202 快乐数

68 阅读2分钟

「这是我参与2022首次更文挑战的第8天,活动详情查看:2022首次更文挑战

题目

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

「快乐数」定义为:

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

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

示例 1:

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

示例 2:

输入:n = 2
输出:false

提示:

  • 1 <= n <= 231 - 1

解题

解题一:判断是否重复(HashSet)

思路

将每一次遍历到的数据存入 HashSet 中,判断是否有重复形成死循环,如果存在重复元素形成死循环,则返回 false,如果没有,最后结果一定为 true

代码

class Solution {

    /**
     * 返回正数每个位置上的数字的平方和
     * @param value
     * @return
     */
    private int getNextValue(int value) {
        int result = 0;
        // 循环遍历数字的每个位置
        while (value / 10 > 0) {
            // 计算最低位的平方和 跟 result 进行累加
            result += Math.pow(value % 10, 2);
            // value除以10,计算高一位的平方和
            value = value / 10;
        }
        // 最高位平方和
        result += Math.pow(value % 10, 2);
        return result;
    }

    public boolean isHappy(int n) {
        Set<Integer> resultSet = new HashSet<>();
        // 判断是否在 resultSet 中
        while (!resultSet.contains(n)) {
            // n == 1,满足快乐数的定义
            if (n == 1) {
                return true;
            }
            // 加入 resultSet 用户判断重复
            resultSet.add(n);
            // 获取下一个数进行判断
            n = getNextValue(n);
        }
        return false;
    }
}

总结

性能分析

  • 执行耗时:1 ms,击败了 88.18% 的 Java 用户
  • 内存消耗:35.5 MB,击败了 36.26% 的 Java 用户

解题一:双指针法(快慢指针)

思路

使用快慢指针思想,其中一个数每次进行一次计算,另一个数每次循环进行两次计算,判断这两个数是否相等,从而判断是否构成死循环,减少内存使用

代码

class Solution {

    /**
     * 返回正数每个位置上的数字的平方和
     * @param value
     * @return
     */
    private int getNextValue(int value) {
        int result = 0;
        // 循环遍历数字的每个位置
        while (value / 10 > 0) {
            // 计算最低位的平方和 跟 result 进行累加
            result += Math.pow(value % 10, 2);
            // value除以10,计算高一位的平方和
            value = value / 10;
        }
        // 最高位平方和
        result += Math.pow(value % 10, 2);
        // 返回计算结果
        return result;
    }

    public boolean isHappy(int n) {
        int slow = getNextValue(n);
        // 判断 n 和 n 转换一次后是否为快乐数,直接返回结果
        if (n == 1 || slow == 1) {
            return true;
        }
        int fast = getNextValue(getNextValue(n));
        while (slow != fast) {
            // 慢数:每次进行一次转换
            slow = getNextValue(slow);
            // 快数:每次进行两次转换
            fast = getNextValue(getNextValue(fast));
            // 其中一个等于 1,代表满足快乐数定义
            if  (slow == 1 || fast == 1) {
                return true;
            }
        }
        // slow == fast 代表形成死循环,无法变成快乐数
        return false;
    }
}

总结

性能分析

  • 执行耗时:1 ms,击败了 88.18% 的 Java 用户
  • 内存消耗:35.2 MB,击败了 86.97% 的 Java 用户