平時不刷題,筆試徒傷悲!力扣力扣 https://leetcode-cn.com/problems/happy-number/
# 202 快樂數
編寫一個算法來判斷一個數 n 是不是快樂數。
「快樂數」定義爲:對於一個正整數,每一次將該數替換爲它每個位置上的數字的平方和,然後重複這個過程直到這個數變爲 1,也可能是 無限循環 但始終變不到 1。如果 可以變爲 1,那麼這個數就是快樂數。
如果 n 是快樂數就返回 True ;不是,則返回 False 。
輸入:19
輸出:true
解釋: 12 + 92 = 82
82 + 22 = 68
62 + 82 = 100
12 + 02 + 02 = 1
方法一:哈希表
算法分爲兩部分(1)給一個數字 nn,它的下一個數字是什麼?(2)按照一系列的數字來判斷我們是否進入了一個循環。
第 1 部分我們按照題目的要求做數位分離,求平方和。
第 2 部分可以使用 HashSet 完成。每次生成鏈中的下一個數字時,我們都會檢查它是否已經在 HashSet 中。(1)如果它不在 HashSet 中,我們應該添加它。(2)如果它在 HashSet 中,這意味着我們處於一個循環中,因此應該返回 false。
class Solution {
public boolean isHappy(int n) {
Set<Integer> hash = new HashSet<>(); // 哈希表存儲
while(n!=1&&!hash.contains(n)){ // n不爲1 & n不在表中
hash.add(n);
n = getNext(n); // 繼續計算
}
return n == 1;
}
public int getNext(int n){ // 計算下一個數,求平方和
int total = 0;
while(n > 0){
int d = n % 10;
n = n / 10;
total = total + d*d;
}
return total;
}
}
/**
* @param {number} n
* @return {boolean}
*/
var isHappy = function(n) {
if(n === 1)
return true;
const list = new Set();
while(!list.has(n)){
list.add(n);
n = next(n);
}
return n===1;
};
function next(n){
n = n + ''
let sum = 0
for(let num of n){
sum += num * num
}
return sum
}
方法二:快慢指針遍歷(弗洛伊德循環查找算法)
那麼這個問題後半部分可以轉換爲檢測一個鏈表是否有環。因此我們在這裏可以使用弗洛伊德循環查找算法。這個算法是兩個奔跑選手,一個跑的快,一個跑得慢。在龜兔賽跑的寓言中,跑的快的稱爲 “烏龜”,跑得快的稱爲 “兔子”。
不管烏龜和兔子在循環中從哪裏開始,它們最終都會相遇。這是因爲兔子每走一步就向烏龜靠近一個節點(在它們的移動方向上)。
在算法的每一步中,慢速在鏈表中前進 1 個節點,快跑者前進 2 個節點(對 getNext(n) 函數的嵌套調用)。(1)如果 n 是一個快樂數,即沒有循環,那麼快跑者最終會比慢跑者先到達數字 1。(2)如果 n 不是一個快樂的數字,那麼最終快跑者和慢跑者將在同一個數字上相遇。
public boolean isHappy(int n) {
int slow = n; // 慢指針
int fast = getNext(n); // 快指針
while(fast!=1 && slow!=fast){
slow = getNext(slow); // 慢指針走一步
fast = getNext(getNext(fast)); // 快指針走兩步
}
return fast==1;
}
var isHappy = function(n) {
let slow = next(n)
let fast = next(slow)
while(slow != fast){
slow = next(slow)
fast = next(next(fast))
}
return slow == 1
}