zoukankan      html  css  js  c++  java
  • Easy | LeetCode 202. 快乐数 | 链表判环 | 数学

    202. 快乐数

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

    「快乐数」定义为:

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

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

    示例 1:

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

    示例 2:

    输入:n = 2
    输出:false
    

    提示:

    • 1 <= n <= 231 - 1

    解题思路

    方法一: 暴力

    直接暴力模拟这个计算过程, 不断使用每一位的平方和向前迭代, 如果迭代的结果是1, 说明是快乐数。如果迭代过程, 出现了循环, 则不是快乐数。判断是否出现循环的过程很简单, 就是使用Set把之前迭代的结果保存起来就可以了。

    时间复杂度:这取决于从第一个数,迭代到第一次出现循环的迭代的次数。

    空间复杂度:和时间复杂度一样。

    public boolean isHappy(int n) {
        Set<Integer> hasExists = new HashSet<>();
        while (n != 1) {
            if (hasExists.contains(n)) {
                return false;
            }
            hasExists.add(n);
            n = bitSquareSum(n);
        }
        return true;
    }
    
    public int bitSquareSum(int x) {
        int sum = 0;
        while (x != 0) {
            int digit = x % 10;
            sum += digit * digit;
            x /= 10;
        }
        return sum;
    }
    

    方法二: 链表判环

    在方法一的基础上做优化, 方法一中需要用Set来保存之前存储过的数字, 来判断是否出现环。其实判环的问题如 Easy | LeetCode 141. 环形链表 使用快慢指针就可以判定是否出现环。

    此题的链表的无环出口就是位平方的结果是1。修改判断链表走到尽头的判断逻辑就可以对环形链表的代码进行改造

    public boolean isHappy(int n) {
        int slow = n, fast = n;
        while (fast != 1) {
            slow = bitSquareSum(slow);
            fast = bitSquareSum(fast);
            if (fast == 1) {
                // 说明链表走到了尽头出口, 链表无环
                return true;
            }
            fast = bitSquareSum(fast);
            if (slow == fast) {
                // 两指针相遇, 说明链表有环
                return false;
            }
        }
        // 快指针走到了链表尽头出口, 说明无环
        return true;
    }
    
    public int bitSquareSum(int x) {
        int sum = 0;
        while (x != 0) {
            int digit = x % 10;
            sum += digit * digit;
            x /= 10;
        }
        return sum;
    }
    

    方法三: 数学

    对这个快乐数, 还有一个规律。虽然我没法证明, 但可以作为一种答案观赏。

    [4 ightarrow 16 ightarrow 37 ightarrow 58 ightarrow 89 ightarrow 145 ightarrow 42 ightarrow 20 ightarrow 4 ]

    这一条循环路径, 是所有的非快乐数的必经之路。

    利用这个规律, 只要判断到某个数走到了上面给的环的某个数字, 就是走到了环的入口, 开始进入环。既不需要用Set存储迭代的数字, 也不需要使用双指针, 直接判断就可。

    public boolean isHappy(int n) {
        Set<Integer> hasExists = new HashSet<>(Arrays.asList(4, 16, 37, 58, 89, 145, 42, 20));
        while (n != 1 && !hasExists.contains(n)) {
            n = bitSquareSum(n);
        }
        return n == 1;
    }
    
    public int bitSquareSum(int x) {
        int sum = 0;
        while (x != 0) {
            int digit = x % 10;
            sum += digit * digit;
            x /= 10;
        }
        return sum;
    }
    
  • 相关阅读:
    Qt新建线程的方法(有QRunnable,QThreadPool,moveToThread和QtConcurrent的例子)
    QThread 与 QObject的关系(QObject可以用于多线程,可以发送信号调用存在于其他线程的slot函数,但GUI类不可重入)
    Qt线程QThread简析(8个线程等级,在UI线程里可调用thread->wait()等待线程结束,exit()可直接退出线程,setStackSize设置线程堆栈,首次见到Qt::HANDLE,QThreadData和QThreadPrivate)
    QSettings保存程序设置
    QList 和std::list的比较
    转义字符()对JavaScript中JSON.parse的影响
    自定义类似QMutexLocker的CMutexLocker
    部件之间图标拖拽(使用很直观,效果很漂亮)
    QtSoap调用Web Service(QtSoap是非官方应用)
    QTableWidget 导出到csv表格
  • 原文地址:https://www.cnblogs.com/chenrj97/p/14619306.html
Copyright © 2011-2022 走看看