1,题目要求
Write an algorithm to determine if a number is “happy”.
A happy number is a number defined by the following process: Starting with any positive integer, replace the number by the sum of the squares of its digits, and repeat the process until the number equals 1 (where it will stay), or it loops endlessly in a cycle which does not include 1. Those numbers for which this process ends in 1 are happy numbers.
Example: 19 is a happy number
如果找到这样的数字返回true,如果陷入循环无法自拔则返回false
2,题目思路
首先,对输入数字n按位获取并计算平方和并不苦难,然后直接用sum记录,如果没有找到,对n进行重新更新为sum,继续寻找。
但是对于跳出的条件很难找到,因为题目的大意是一直都找不到会陷入死循环,当然题目不可以这样做。一开始的思路就是认为设置一个阈值,超过这个值就自动跳出。设置了1000,虽然是AC,但是速度极慢。看个排名第一的答案,思路一样,但是阈值是10。修改过阈值后效率提升了,而且阈值还可以进一步的减少,但是这种办法感觉并不好。
查看一个Java方法,觉得思路不错:
用到set的方法,也就是集合。该方法的特点是不允许重复添加相同的元素。因此,如果添加元素失败时,说明该数字在前面已经进行处理并判断不可行了,又循环回来,这个时候便可以直接跳出循环即可。
3,程序源码
class Solution {
public:
bool isHappy(int n) {
set<int> inLoop = {};
int squareSum,remain;
while(inLoop.insert(n).second)
{
squareSum = 0;
while(n > 0)
{
remain = n % 10;
squareSum += remain * remain;
n /=10;
}
if(squareSum == 1)
return true;
else
n = squareSum;
}
return false;
}
};
关于程序,set的用法和java的方式有很大的不同。
set的特性是,所有元素都会根据元素的键值自动排序,set的元素不像map那样可以同时拥有实值(value)和键值(key),set元素的键值就是实值,实值就是键值。set不允许两个元素有相同的键值。
set的各成员函数列表如下:
begin()–返回指向第一个元素的迭代器
clear()–清除所有元素
count()–返回某个值元素的个数
empty()–如果集合为空,返回true
end()–返回指向最后一个元素的迭代器
equal_range()–返回集合中与给定值相等的上下限的两个迭代器
erase()–删除集合中的元素
find()–返回一个指向被查找到元素的迭代器
get_allocator()–返回集合的分配器
insert()–在集合中插入元素
lower_bound()–返回指向大于(或等于)某值的第一个元素的迭代器
key_comp()–返回一个用于元素间值比较的函数
max_size()–返回集合能容纳的元素的最大限值
rbegin()–返回指向集合中最后一个元素的反向迭代器
rend()–返回指向集合中第一个元素的反向迭代器
size()–集合中元素的数目
swap()–交换两个集合变量
upper_bound()–返回大于某个值元素的迭代器
value_comp()–返回一个用于比较元素间的值的函数
C++中set的用法
特别注意的是,对于insert(Type value)方法来说,它的返回对象为一个pair对象,该对象包含一个迭代器和一个bool值,迭代器指向拥有该键的元素,而bool值表明是否添加了元素。
迭代器用first来获得,bool值用second来获得。
因此,例如对于set tmp = {1,2,3},当进行插入操作tmp.insert(1),因为本身set中是有1的,所以,
tmp.insert(1).first是一个指针,存储1所在的地址,因此*tmp.insert(1).first = 1;
tmp.insert(1).second是一个bool值,因为插入是失败的(false),因此tmp.insert(1).second = 0;