33、快乐数
题目
33.0、暴力解法
先写一个函数来计算每个位置的平方和,该函数对于下列三种方法通用
int calculate(int n)
{
int m = 0;
while (n)
{
m += (int)pow(n % 10, 2);
n /= 10;
}
return m;
}
暴力解法比较实际,用一个哈希集合来记录每次的数从而来判断是否存在循环
//暴力解法
bool isHappy0(int n)
{
unordered_set<int> data;
while (!data.count(n))
{
if (n == 1)return true;
data.insert(n);
n = calculate(n);
}
return false;
}
时间复杂度:O(log n)对于通用函数的时间复杂度是log n,从开始到1或者发现循环的个数是常量(数学上可以证明)
空间复杂度:不一定,我直接一个不一定
33.1、快慢指针
这个和那个判断链表是否存在环类似,使用一前一后两个指针来判断是否在存在循环
//快慢指针
bool isHappy1(int n)
{
int slownum = n, fastnum = calculate(n);
while (fastnum != 1 && slownum != fastnum)
{
slownum = calculate(slownum);
fastnum = calculate(calculate(fastnum));
}
return fastnum == 1;
}
时间复杂度:O(log n)同上
空间复杂度:O(1)
33.2、数学
研究一下可以发现,只有一个循环【4,16,37,58,89,145,42,,20 ,4】
所以只需要判断每一次的数是否在这个序列里面就可以判断是否存在循环了
//数学方法
bool isHappy2(int n)
{
unordered_set<int> data = { 4, 16, 37, 58, 89, 145, 42, 20 };
while (!data.count(n))
{
if (n == 1)return true;
n = calculate(n);
}
return false;
}
时间复杂度:O(log n)同上
空间复杂度:O(1)集合是一个常量