一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第26天,点击查看活动详情。
每日刷题 2021.04.26
- leetcode原题链接:
- 难度:简单
- 方法:map集合、循环链表
题目
- 编写一个算法来判断一个数 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
解题思路
- 仔细读题,看题目中加粗的字体。其实就已经告诉了我们有两种情况:
- 1.数循环变为1
- 2.数无限循环
- 需要模拟题目中将当前的数
n逐位分开后,对其平方后,再加和起来。可以看到我们只需要写好一次的操作,后面的操作,可以通过不断的重复这段操作来实现。- 临界条件:
n / 10 == 0的时候,表示所有的位数都已经处理过了。 - 一次的逻辑:(获取)取余
10,得到最后一位的数值,(处理)将其平方;再(获取)将当前的数/ 10,丢掉已经处理过的最后一位数值,得到下一轮的开始值。
- 临界条件:
map集合
- 因为有可能会存在循环,因此可以将已经得到的数值,存储在
map集合中,如果下一次计算的结果,已经在map集合中,那么就说明,进入了循环,直接返回false。 - 与之而来的问题:如果数值很多很大的时候,
map集合不足以存储这些所有的数值,那么如何优化呢?
循环链表
- 分析本题可知,有一种情况可能会无限循环,那么就可以将题转换成:判断链表有环还是无环。
- 有环 =>
false - 无环 =>
true
- 有环 =>
- 判断链表中是否存在环的经典做法,就是使用快慢指针。记慢指针
last,快指针fast。如果链表中存在环,那么快指针一定会和慢指针相遇;如果无环,则快指针先到达终点。 - 适用到本题上,就是简化掉链表的数据结构,单纯的去判断
fast和last指向的数值,是否有重复的,如果相等,则存在无限循环。 - 因此总结两种情况:
- 当快慢指针所代表的值相同时,直接返回
false - 当快指针等于
1的时候,跳出循环,返回true
- 当快慢指针所代表的值相同时,直接返回
- 注意⚠️:需要特别注意,如果你一开始赋值的时候,将快慢指针初始化为一样的值,那么就需要在执行完第一次之后,再判断
last和fast是否相等。
AC代码
循环链表
var isHappy = function(n) {
// 快乐就完事了
// 通过题目所给的分析可知:循环可以使用循环链表来进行判断
// 三种情况: 变为1 / 无限循环 / 无穷大
// 检测循环链表的方法:快慢指针
// 如果存在环,那么快慢指针就会相遇
let getNext = function (n) {
return n.toString().split('').map(i => i ** 2).reduce((a, b) => a + b);
}
let slow = n,fast = n,flag = false;
while(fast != 1) {
if(slow == fast && flag) return false;
flag = true;
slow = getNext(slow);
fast = getNext(getNext(fast));
}
return true;
};
总结
- 读题还需要再认真一些,多注意加粗的字体表示的含义,读好题,思路想清楚,再敲代码。