題目
編寫一個算法來判斷一個數是不是“快樂數”。
一個“快樂數”定義爲:對於一個正整數,每一次將該數替換爲它每個位置上的數字的平方和,然後重複這個過程直到這個數變爲 1,也可能是無限循環但始終變不到 1。如果可以變爲 1,那麼這個數就是快樂數。
bool isHappy(int n) {
//在這裏填寫代碼
}
示例:
輸入: 19
輸出: true
解釋:
1^2 + 9^2 = 82
8^2 + 2^2 = 68
6^2 + 8^2 = 100
1^2 + 0^2 + 0^2 = 1
題解
思路:
- 首先做狀態數估算,因爲 n 爲整形,當 n = 999999999 時,一次運算後得到 9 * 9 ^ 2 = 729 是最大值,整個運算過程中不可能會得到比這個值大的數,而這個數之下當n = 699 時得到最大值,值爲 6 ^ 2 + 2 * 9 ^2 = 198。
- 所以可以先對1 — 198 進行一次打表(可以用記憶化的技巧),然後對 n 做兩次運算,直接根據表得到答案。或者當運算循環200次還沒有得到 1 ,就說明運算過程中出現了環,不可能得到1。
- 還有一種比較優的思路,因爲狀態數是有限且較小的,我們也可以用鏈表判環的思想去解題,將每個數看做鏈表的一個節點,一次運算後得到的數看做該節點的next,出現環則不可能得到 1。鏈表判環詳見LeetCode_141. 環形鏈表
note:只判斷快指針(或者叫快數)是否等於1就可以,而且不會出先鏈表中容易犯的訪問NULL->next的錯誤
這裏只實現鏈表判環的思路
int nextNum(int num) {
int next = 0, temp;
while (num) {
temp = num % 10;
next += temp * temp;
num /= 10;
}
return next;
}
bool isHappy(int num) {
int slow = num, quick = nextNum(num);
while (quick != slow && quick != 1) {
quick = nextNum(quick);
quick = nextNum(quick);
slow = nextNum(slow);
}
return quick == 1;
}