本文主要是介绍双指针练习:快乐数,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
1.题目链接:202.快乐数
2.题目描述:
编写一个算法来判断一个数 n 是不是快乐数。
「快乐数」 定义为:
- 对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。
- 然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。
- 如果这个过程 结果为 1,那么这个数就是快乐数。
如果 n 是 快乐数 就返回 true ;不是,则返回 false 。
3.题目分析:
1.根据题意以及测试用例我们发现,我们会频繁的对一个数进行取余 求余方 再取模。
因此,我们可以写一个函数封装这个操作。如何求一个数n每个位置上的数字的平方和?
a.把数 n 每一位的数提取出来
i. int t = n % 10 提取个位;
ii. n = n / 10 干掉个位;
直到 n 的值变为0;
b.提取每一位的时候,用一个变量 tmp 记录这一位的平方与之前提取位数的平方和
tmp = tmp + t * t
2.拿到一个题,我们先分析一个案例,例如 n = 19
如果n = 2
由此我们可以发现:如果数n 是一个快乐数,它的最后一个数是1
如果数n 不是快乐数,它最终会形成一个环,不停的循环下去。
接着我们拓展一个原理:鸽巢原理(抽屉原理)
n个巢,有n+1个鸽子,可以推出至少有一个巢,里面的鸽子数大于1;
因此我们来看题目范围
这是一个整形的最大数,大约为 2.1*10^9
我们可以假设一个比他更大的数 整形最大数约为10位数,且最大的数一定不会超过99999 99999
我们来计算这个数每个位置上的数字的平方和,9^2 * 10 = 810,也就是最大的数是810
题目n最小为1,所以每个位置上的数字平方和的范围在 [1,810] 之间,有810个数。
由此可以推出:一个数经过不停的分割成下一个数,经过811次 这个分割后的数一定会出现重复的情况,也就是会进环,因此我们使快慢指针追击即可
代码:
class Solution {
public:// 封装一个函数,实现个位数字平方和相加int bitSum(int n){int sum = 0;//定义相加后的结果while(n){//不停的取模取余,直到这个数为0为止int bit = n % 10;n = n/10;sum += bit * bit;}return sum;}bool isHappy(int n) {int slow = n;int fast = bitSum(n);//下一次被操作数的结果while(slow != fast){slow = bitSum(slow);//slow走一步fast = bitSum(fast);fast = bitSum(fast);//fast走两步//根据鸽巢原理可知,slow和fast一定会相遇}return slow == 1;//判断最后结果是不是1}
};
这篇关于双指针练习:快乐数的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!