题目描述
判断一个正整数是否是快乐数字? 如果一个数字能够通过有限次快乐变换成为1,则是快乐数字。 快乐变换是对一个数字的每一位的平方数求和。
例如: 对于68
- 68 => 6^2+8^2= 100
- 100 =>1^2+0^2+0^2=1
所以68是一个快乐数字。
输入输出
输入
- 第一行是n; 如果n为-1,表示输入结束
输出
- 针对每组数据,输出是否是快乐数字 true/false
示例输入
68
-1
示例输出
true
题目分析
先来分析一下时间复杂度,对于给定的一个数,事先不知道会计算多少次,对于10^6的输入,最后变成810以内的数字的快乐变换,所以该题目的时间负责度为O(1)。
一个简单的解法:
#include <iostream>
#include <fstream>
#include <set>
using namespace std;
class HappyNum {
public:
bool isHappy(int n) {
set<int> cache;
while (cache.insert(n).second) n=transform(n);
return n==1;
}
int transform(int n) {
int result = 0;
while (n != 0) {
result += (n%10) * (n%10);
n /= 10;
}
return result;
}
};
int main() {
ifstream in("input.txt");
string inNumStr;
HappyNum ha;
while (getline(in, inNumStr)) {
int n = atoi(inNumStr.c_str());
if (n != -1) {
ha.isHappy(n) ? printf("true\n") : printf("false\n");
}
}
in.close();
return 0;
}
这是一个简单的实现方法,既然要做那就要做到极致,加入BigData的思维,如果这样的数字有成千上万个,每一个数字都要计算一次显然是不合理的,把cache变成全局变量,可以做进一步的优化。
#include <iostream>
#include <fstream>
#include <map>
using namespace std;
map<int, bool> cache;
class HappyNum {
public:
bool isHappy(int n, int deep) {
if (cache.find(n) != cache.end()) {
printf("%d\n", deep);
return cache[n];
}
cache[n] = false;
cache[n] = isHappy(transform(n), deep+1);
return cache[n];
}
int transform(int n) {
int result = 0;
while (n != 0) {
result += (n%10) * (n%10);
n /= 10;
}
return result;
}
};
int main() {
ifstream in("input.txt");
string inNumStr;
HappyNum ha;
cache[1] = true;
while (getline(in, inNumStr)) {
int n = atoi(inNumStr.c_str());
if (n != -1) {
ha.isHappy(n, 1) ? printf("true\n") : printf("false\n");
}
}
in.close();
return 0;
}
更进一步考虑这个问题,上述的实现中,使用了cache作缓存,将已经获得的结果记录下来,并且使用的递归调用,而对于大部分的数字,比如10位数9999999999,快乐变化为810,所以我们可以事先得到810以前的数字,然后再判断给定的数字,这样可以进一步优化缓存空间。
#include <iostream>
#include <fstream>
#include <map>
using namespace std;
map<int, bool> cache;
class HappyNum {
public:
bool isHappy(int n, int deep) {
if (cache.find(n) != cache.end()) {
printf("%d\n", deep);
return cache[n];
}
cache[n] = false;
cache[n] = isHappy(transform(n), deep+1);
return cache[n];
}
int transform(int n) {
int result = 0;
while (n != 0) {
result += (n%10) * (n%10);
n /= 10;
}
return result;
}
};
int main() {
ifstream in("input.txt");
string inNumStr;
HappyNum ha;
cache[1] = true;
for (int i=0; i<=810; ++i) {
ha.isHappy(i, 1);
}
while (getline(in, inNumStr)) {
int n = atoi(inNumStr.c_str());
if (n != -1) {
ha.isHappy(n, 1) ? printf("true\n") : printf("false\n");
}
}
in.close();
return 0;
}