LeetCode202. 快乐数

题目

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

快乐数定义为:对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和,然后重复这个过程直到这个数变为 1,

也可能是 无限循环 但始终变不到 1。如果 可以变为  1,那么这个数就是快乐数。如果 n 是快乐数就返回 True ;不是,则返回 False 。

分析

本题开始一头雾水,因为可能无限循环。这题关键就在此。思考怎样会出现出现无限循环?也就是什么情况下会判定为非快乐数?

如果当前计算得到的各位平方和之前出现过,意味着就出现了循环,以后还是循环。。。这就相当于找一个数之前是否出现过。

这很明显就是用哈希中的set集合,因为集合不同的元素具有唯一性,用find查找集合即可。

代码

 1 class Solution {
 2 public:
 3     //取每位上的数的平方之和
 4     int sum(int n){
 5         int s = 0;
 6         //如何取每位上的数?对10取余再除以10
 7         while(n){
 8             s += (n%10) * (n%10);
 9             n /= 10;
10         }
11         return s;
12     }
13     bool isHappy(int n) {
14         unordered_set<int>st;
15         while(1){
16             int res = sum(n);
17             if(res == 1) return true;
18             auto it = st.find(res);
19             if(it != st.end()) return false;
20             st.insert(res);
21             n = res;
22         }
23     }
24 };

法二、快慢指针判断循环,其实就是弗洛伊德判圈算法(龟兔赛跑)

想象一下,假设有两个小孩子在一个“可以无限向前跑”的跑道上赛跑,同时出发,但其中一个小孩的速度是另一个的两倍。如果跑道是直的,跑的快的永远在前面;但是如果跑道有环的话,则跑的快的小孩子将追上跑的慢的小孩。就是套圈了!

快指针每次比慢指针多走一步,所以快指针的路程的慢指针的2倍,当慢指针走完一圈,快指针正好走完两圈,两指针重合。

class Solution {
public:
    //取每位上的数的平方之和
    int sum(int n){
        int s = 0;
        //如何取每位上的数?对10取余再除以10
        while(n){
            s += (n%10) * (n%10);
            n /= 10;
        }
        return s;
    }
    bool isHappy(int n) {
        int slow = sum(n);
        int fast = sum(sum(n));
        while(fast != slow ){
            slow = sum(slow);
            fast = sum(sum(fast));
        }
        return slow == 1;
    }
};

注意非快乐数出现的死循环就是有环,判断有环用快慢指针,相遇说i明有环,最后看下相遇点是否是1

本题和链表中的判断是否有环一样

原文地址:https://www.cnblogs.com/fresh-coder/p/14293634.html