题目
编写一个算法来判断一个数 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 引起的循环,是的话就是快乐数,否则不是快乐数。
注意:此题不建议用集合记录每次的计算结果来判断是否进入循环,因为这个集合可能大到无法存储;另外,也不建议使用递归,同理,如果递归层次较深,会直接导致调用栈崩溃。不要因为这个题目给出的整数是 int 型而投机取巧。
为啥一定不会出现死循环,因为int类型最大值为为2 147 483 647, 所以平方和最大的数是1 999 999 999,平方和为1 + 81*9 = 724。任何数的平方和都在1到724之间,724次循环之内一定有重复的
c++解法
class Solution { public: int bitSquareSum(int n) { int sum = 0; while(n > 0) { int bit = n % 10; sum += bit * bit; n = n / 10; } return sum; } bool isHappy(int n) { int slow = n, fast = n; do{ slow = bitSquareSum(slow); fast = bitSquareSum(fast); fast = bitSquareSum(fast); }while(slow != fast); return slow == 1; } };
方法二:哈希表
class Solution { public: int bitSquareSum(int n){ int sum=0; while(n>0){ int bit=n%10; sum+=bit*bit; n=n/10; } return sum; } bool isHappy(int n) { unordered_set<int> set; while(true){ int sum=bitSquareSum(n); if(sum==1){ return true; } //如果这个sum曾经出现过,说明已经陷入了无限循环了,立刻return false if(set.find(sum)!=set.end()){ return false; } else{ set.insert(sum); } n=sum; } } };
java
class Solution { public boolean isHappy(int n) { Set<Integer> set=new HashSet<>(); while(n!=1){ if(set.contains(n)) return false; set.add(n); String s=String.valueOf(n); int tmp=0; for(int i=0;i<s.length();i++){ int num=s.charAt(i)-'0'; tmp+=num*num; } n=tmp; } return true; } }
或者
class Solution { int bitSquareSum(int n){ int res=0; while(n>0){ int num=n%10; res+=num*num; n/=10; } return res; } public boolean isHappy(int n) { Set<Integer> set=new HashSet<>(); while(n!=1){ if(set.contains(n)) return false; set.add(n); n=bitSquareSum(n); } return true; } }