快樂數--快慢指針

0x01.問題

編寫一個算法來判斷一個數 n 是不是快樂數。

「快樂數」定義爲:對於一個正整數,每一次將該數替換爲它每個位置上的數字的平方和,然後重複這個過程直到這個數變爲 1,也可能是 無限循環 但始終變不到 1。如果 可以變爲 1,那麼這個數就是快樂數。

如果 n 是快樂數就返回 True ;不是,則返回 False

示例:

輸入:19
輸出:true
解釋:
1^2 + 9^2 = 82
8^2 + 2^2 = 68
6^2 + 8^2 = 100
1^2 + 0^2 + 0^2= 1

public boolean isHappy(int n)

0x02.解決思路

讀題,發現題目要點:

  • 判斷一個數,經過一系列【每一次將該數替換爲它每個位置上的數字的平方和】操作,是否可以變成1。

問題其實很簡單,只需要不斷的模擬這個過程變換就可以了,但是,在裏面會存在一些問題。

如果它永遠不會變成1,那麼它會怎樣變換呢?

一種想法是,它會越來越大,越來越大,最後會超出整型的範圍,但是我們可以拿個具體的例子看一下。

  • 三位數經過這個操作能得到的最大的數字是999—>243,四位數是9999—>324

  • 再來看一下接近整型的大數9999999999999—>1053

我們發現,其實並不會大到超出整型的範圍,而是會在一個很小的範圍內變換
,那麼在這個小範圍的變換就只有兩種情況了。

  1. 最後變成1。
  2. 不斷循環。

第一種情況是我們需要的,我們只需要判斷是否出現循環就行了,如果出現了循環,並且還沒有得到1,說明之後是不可能再得到1了的。

如何判斷是否出現循環了呢?很簡單,只需要判斷當次得到的數是否已經出現過就行了。那麼我們可以使用一個哈希表存儲一下每次得到的數,如果當次得到的數已經出現過了,那麼直接返回false

class Solution {
    private int next(int n){
        int ans=0;
        while(n>0){
            int d=n%10;
            n/=10;
            ans+=d*d;
        }
        return ans;
    }
    public boolean isHappy(int n) {
        Set<Integer> hash=new HashSet<>();
        while(n!=1&&!hash.contains(n)){
            hash.add(n);
            n=next(n);
        }
        return n==1;
    }
}

這種方法是最簡單,最直接的。

其實,判斷是否出現循環,還有另外一種常用的方法,快慢指針,跟判斷鏈表是否成環思路一樣。

0x03.解決代碼–快慢指針

class Solution {
    private int next(int n){
        int ans=0;
        while(n>0){
            int d=n%10;
            n/=10;
            ans+=d*d;
        }
        return ans;
    }
    public boolean isHappy(int n) {
        int slow=n;
        int fast=next(n);
        while(fast!=1&&fast!=slow){
            slow=next(slow);
            fast=next(next(fast));
        }
        return fast==1;
    }
}

ATFWUS --Writing By 2020–04-30

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章