Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[LeetCode] 202. Happy Number #202

Open
grandyang opened this issue May 30, 2019 · 1 comment
Open

[LeetCode] 202. Happy Number #202

grandyang opened this issue May 30, 2019 · 1 comment

Comments

@grandyang
Copy link
Owner

grandyang commented May 30, 2019

 

Write an algorithm to determine if a number is "happy".

A happy number is a number defined by the following process: Starting with any positive integer, replace the number by the sum of the squares of its digits, and repeat the process until the number equals 1 (where it will stay), or it loops endlessly in a cycle which does not include 1. Those numbers for which this process ends in 1 are happy numbers.

Example: 

Input: 19
Output: true
Explanation: 
1^2 + 9^2 = 82
8^2 + 2^2 = 68
6^2 + 8^2 = 100
1^2 + 0^2 + 0^2 = 1

Credits:
Special thanks to @mithmatt and @ts for adding this problem and creating all test cases.

 

这道题定义了一种快乐数,就是说对于某一个正整数,如果对其各个位上的数字分别平方,然后再加起来得到一个新的数字,再进行同样的操作,如果最终结果变成了1,则说明是快乐数,如果一直循环但不是1的话,就不是快乐数,那么现在任意给我们一个正整数,让我们判断这个数是不是快乐数,题目中给的例子19是快乐数,那么我们来看一个不是快乐数的情况,比如数字11有如下的计算过程:

1^2 + 1^2 = 2
2^2 = 4
4^2 = 16
1^2 + 6^2 = 37
3^2 + 7^2 = 58
5^2 + 8^2 = 89
8^2 + 9^2 = 145
1^2 + 4^2 + 5^2 = 42
4^2 + 2^2 = 20
2^2 + 0^2 = 4

我们发现在算到最后时数字4又出现了,那么之后的数字又都会重复之前的顺序,这个循环中不包含1,那么数字11不是一个快乐数,发现了规律后就要考虑怎么用代码来实现,我们可以用 HashSet 来记录所有出现过的数字,然后每出现一个新数字,在 HashSet 中查找看是否存在,若不存在则加入表中,若存在则跳出循环,并且判断此数是否为1,若为1返回true,不为1返回false,代码如下:

 

解法一:

class Solution {
public:
    bool isHappy(int n) {
        unordered_set<int> st;
        while (n != 1) {
            int sum = 0;
            while (n) {
                sum += (n % 10) * (n % 10);
                n /= 10;
            }
            n = sum;
            if (st.count(n)) break;
            st.insert(n);
        }
        return n == 1;
    }
};

 

其实这道题也可以不用 HashSet 来做,我们并不需要太多的额外空间,关于非快乐数有个特点,循环的数字中必定会有4,这里就不做证明了,我也不会证明,就是利用这个性质,就可以不用set了,参见代码如下:

 

解法二:

class Solution {
public:
    bool isHappy(int n) {
        while (n != 1 && n != 4) {
            int sum = 0;
            while (n) {
                sum += (n % 10) * (n % 10);
                n /= 10;
            }
            n = sum;
        }
        return n == 1;
    }
};

 

这道题还有一种快慢指针的解法,由热心网友喵团团提供,跟之前那道 Linked List Cycle 检测环的方法类似,不同的是这道题环一定存在,不过有的环不符合题意,只有最后 slow 停在了1的位置,才表明是一个快乐数。而且这里每次慢指针走一步,快指针走两步,不是简单的指向next,而是要调用子函数计算各位上数字的平方和,当快慢指针相等时,跳出循环,并且判断慢指针是否为1即可,参见代码如下:

 

解法三:

class Solution {
public:
    bool isHappy(int n) {
        int slow = n, fast = n;
        while (true) {
            slow = findNext(slow);
            fast = findNext(fast);
            fast = findNext(fast);
            if (slow == fast) break;
        }
        return slow == 1;
    }
    int findNext(int n) {
        int res = 0;
        while (n > 0) {
            res += (n % 10) * (n % 10);
            n /= 10;
        }
        return res;
    }
};

 

类似题目:

Linked List Cycle

Add Digits

Ugly Number

 

参考资料:

https://leetcode.com/problems/happy-number/

https://leetcode.com/problems/happy-number/discuss/56913/Beat-90-Fast-Easy-Understand-Java-Solution-with-Brief-Explanation

https://leetcode.com/problems/happy-number/discuss/56917/My-solution-in-C(-O(1)-space-and-no-magic-math-property-involved-)

 

LeetCode All in One 题目讲解汇总(持续更新中...)

@lld2006
Copy link

lld2006 commented Jul 7, 2020

在讨论中, 有人指出, 解法三可以在fast得出结果后检查一下是否fast是1, 这在happy number的情况下可以少循环一些次数。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants