【LeetCode面试150】——202快乐数
博客昵称:沈小农学编程
作者简介:一名在读硕士,定期更新相关算法面试题,欢迎关注小弟!
PS:哈喽!各位CSDN的uu们,我是你的小弟沈小农,希望我的文章能帮助到你。欢迎大家在评论区唠嗑指正,觉得好的话别忘了一键三连哦!😘
题目难度:简单
默认优化目标:最小化时间复杂度。
Python默认为Python3。
1 题目描述
编写一个算法来判断一个数 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
2 题目分析
输入是一个整数n,输出是布尔值。约束条件是,如果是快乐数,返回true;反之,返回false。
根据快乐数的定义,我们猜测有以下三种可能:
-
最终到1
-
最终会进入循环
-
值会越来越大,最后到无穷大
到1的情况如下图所示:
循环的情况如下图所示:
现在我们来分析第三种情况。
我们对不同位数的数取最大值,看看它们的下一个数和它们自身相比的是变大还是变小了。
位数 | 最大 | 下一个数 |
---|---|---|
1 | 9 | 81 |
2 | 99 | 162 |
3 | 999 | 243 |
4 | 9999 | 324 |
13 | 9999999999999 | 1053 |
对于三位数字,他不可能大于243;而在4位以及4位以上的数字,最终也会跌落到3位数。所以,在最坏情况下,算法会在243以下的数字上循环,要么继续循环,要么到1。所以不会出现第三种情况。
3 代码实现
3.1 哈希表
我们使用哈希表记录已经出现过的快乐数,用于检查某个数是否在循环链当中。
时间复杂度O(log n),空间复杂度O(log n)。当n足够大时,这和n的位数有关,即log n。
C++代码实现
class Solution {
public:
bool isHappy(int n) {
auto getNext = [](int n) {
int sum = 0;
while (n > 0) {
int digit = n % 10;
n /= 10;
sum += digit * digit;
}
return sum;
};
std::unordered_set<int> seen;
while (n != 1 && seen.find(n) == seen.end()) {
seen.insert(n);
n = getNext(n);
}
return n == 1;
}
};
Python代码实现
class Solution:
def isHappy(self, n: int) -> bool:
def nexthappy(n):
sum=0
while n>0:
n,d=divmod(n,10)
sum+=d**2
return sum
seen=set()
while n!=1 and n not in seen:
seen.add(n)
n=nexthappy(n)
return n==1
3.2 快慢指针法
我们使用两个指针,一个叫“兔子”,一个叫“乌龟”。“兔子”一次前进两格,“乌龟”一次一格。如果n是一个快乐数,即没有循环,那么快跑者会比慢跑者先到达数字1;反之,会在同一个数上相遇。
时间复杂度O(log n),空间复杂度O(1)。
C++代码实现
class Solution {
public:
bool isHappy(int n) {
auto getNext = [](int n) {
int sum = 0;
while (n > 0) {
int digit = n % 10;
n /= 10;
sum += digit * digit;
}
return sum;
};
int slow = n;
int fast = getNext(n);
while (fast != 1 && slow != fast) {
slow = getNext(slow);
fast = getNext(getNext(fast));
}
return fast == 1;
}
};
Python代码实现
class Solution:
def isHappy(self, n: int) -> bool:
def nexthappy(n):
sum=0
while n>0:
n,d=divmod(n,10)
sum+=d**2
return sum
slow=n
fast=nexthappy(n)
while fast!=1 and slow!=fast:
slow=nexthappy(slow)
fast=nexthappy(nexthappy(fast))
return fast==1
参考文献
力扣面试经典150题
力扣官方题解