---
description: 15 算出 1² + 5² 可以先拆解成 15%10 + Math.floor(15/10)
---

# # 202 Happy Number

[LeetCode](https://leetcode.com/problems/happy-number/)

```
write an algorithm to determine if a number is "happy".

A happy number is a number defined by the following process: 
Starting with any positive integer, replace the number by the sum of the squares of its digits, 
and repeat the process until the number equals 1 (where it will stay), 
or it loops endlessly in a cycle which does not include 1. 
Those numbers for which this process ends in 1 are happy numbers.
```

```
Example: 

Input: 19
Output: true
Explanation: 
1² + 9² = 82
8² + 2² = 68
6² + 8² = 100
1² + 0² + 02 = 1

/**
 * @param {number} n
 * @return {boolean}
 */
var isHappy = function(n) {
    
};
```

### Edge Case

* 可能會有一樣的值 \[1, 2, 1]
* 如果只有一個值 \[1]
* 值不是數字 ( 但題目已經說一定是數字所以這種狀況就不用再判斷了 )

### 怎麼解

* 使用一個 set 儲存計算過的數字，如果目前的數字已經計算過，表示無窮迴圈出現，return false。
* 怎麼把 21 拆成 2, 1 然後個別做運算呢? 直覺會想 .toString().split('').forEach 先轉成字串再轉陣列再用陣列方法解

```
var isHappy = function(n) {
    let store = new Set();
    // 當等於 1 (Happy Number) 或是重覆數字出現 (無窮迴圈) 就停
    while(n!==1 && !store.has(n)){
        store.add(n)
        n = n.toString().split('').reduce((acc, cur) => acc +  Math.pow(cur, 2), 0);
    }
   
    return n ==1;
};
```

### 改善

先轉成字串再轉陣列再用陣列方法解"，轉來轉去之中也影響了效能。其實可以這樣做，先從個位數算再算十位數，效能也隨之增加

```
15 可以分成 5 跟 1 
15%10 = 5 
Math.floor(15/10) = 1
```

```
var isHappy = function(n) {
    let store = new Set();
    // 當等於 1 (Happy Number) 或是重覆數字出現 (無窮迴圈) 就停
    while(n!==1 && !store.has(n)){
        store.add(n)
        n = cal(n);
        // n = n.toString().split('').reduce((acc, cur) => acc +  Math.pow(cur, 2), 0);
    }
    function cal(x){
        var result = 0;
        while(x>0){
            result += (x%10)*(x%10);
            x = Math.floor(x/10)
        }
        return result;
    }
    
    return n ==1;
};
```

### 學到什麼?

input 若是一個數字，而要針對個別數字做運算，就可以考慮以上方法
