題目描述
編寫一個算法來判斷一個數是不是“快樂數”。
題目來源:LeetCode
一個“快樂數”定義爲:對於一個正整數,每一次將該數替換爲它每個位置上的數字的平方和,然後重複這個過程直到這個數變爲 1,也可能是無限循環但始終變不到 1。如果可以變爲 1,那麼這個數就是快樂數。
示例:
輸入: 19
輸出: true
解釋:
12 + 92 = 82
82 + 22 = 68
62 + 82 = 100
12 + 02 + 02 = 1
解題思路
這是一個在編程的時候會出現死循環的問題,個人認爲重點工作其實倒不是怎麼判斷是不是快樂數,而是找到打破循環的方法或者條件。
- 思路1 :快慢指針
慢指針slower每次前進一步(進行一次平方計算),快指針faster每次前進兩步(進行兩次平方計算),當slower和faster不相等的時候,就一直循環。那爲啥還說能打破循環呢?
這是因爲當快慢指針相等的時候會停止循環,相等的有兩種情況:- 當慢指針和快指針都通過計算變成了1;
- 當慢指針走過一圈之後,快指針肯定恰好走過了兩圈,如果不是快樂數,快慢指針的值肯定是相同的;
之所以選擇快指針走兩步而不是三步四步,是因爲1,2公倍數最小,公約數最多,這樣最節省空間和時間
- 思路2 :藉助HashSet
哈希Set特點就是不允許重複,那隻要每次求和之後,判斷當前的值n是否已經存在於hashset中就好啦,存在就不是快樂數,直接return false,不存在就添加進hashset,直到n 變成1跳出循環,或者返回false。 - 思路3 :投機取巧
小於10的數中,只有1和7是快樂數,借鑑leetcode上大神的思路,所以,投機取巧就很簡單了:- 只要每次計算得到的n大於10,那麼就繼續計算;
- 每次計算得到的n小於10,如果等於1或者7,就是快樂數,不等就不是。
代碼實現(Java)
/**
* @author : flower48237
* @2020/3/16 20:38
* title : LeetCode精選TOP面試題202.快樂數
*/
public class Solution3 {
public boolean isHappy(int n) {
// 法 1 -- 快慢指針
int slower = n;
int faster = n;
do {
slower = getSqrtSum(slower);
faster = getSqrtSum(faster);
faster = getSqrtSum(faster);
}while (slower != faster);
return slower == 1;// 返回slower和1是否相等的判定值
// 法 2 -- 藉助HashSet
HashSet<Integer> hashset = new HashSet<Integer>();
hashset.add(n);
if (n == 1){
return true;
}
while (n != 1){
n = getSqrtSum(n);
if (hashset.contains(n)){
return false;
}
hashset.add(n);
}
return true;
// 法 3 -- 投機取巧
while (true){
if (n < 10){
if (n == 1 || n == 7) {
return true;
}else {
return false;
}
}
n = getSqrtSum(n);
}
}
// 三個方法都會用到的計算平方的步驟
public int getSqrtSum(int num){
int sum = 0;
while (num > 0){
int item = num % 10;
sum += item * item;
num /= 10;
}
return sum;
}
}