LeetCode演算法題-Happy Number(Java實現)
這是悅樂書的第188 次更新,第190 篇原創
01 看題和準備
今天介紹的是LeetCode演算法題中Easy級別的第47題(順位題號是202)。編寫演算法以確定數字是否“幸福”。
幸福數字是由以下過程定義的數字:從任何正整數開始,將數字替換為其數字的平方和,並重復該過程,直到最後數字等於1。這個過程以1結尾的那些數字是幸福的數字。如果陷入無限迴圈則不是幸福數字。例如:
輸入:19
輸出:true
說明:
1x1 + 9x9 = 82
8x8 + 2x2 = 68
6x6 + 8x8 = 100
1x1 + 0x0 + 0x0 = 1
本次解題使用的開發工具是eclipse,jdk使用的版本是1.8,環境是win7 64位系統,使用Java語言編寫和測試。
02 第一種解法
從題目給的例子可以看出,每獲得一個新的數字,都需要按照個十百位拆分然後計算乘積,直到最後得到的是1為止,而那些不是幸福數字的數,會陷入死迴圈裡面,因此,我們需要將每次新計算得到的結果儲存起來,如果下次計算的時候遇到,可以直接判斷該數字不是幸福數字,因此我們使用HashMap來存值,使用遞迴來迴圈處理資料。因為需要多次使用Map,所以將其定義在方法外面,可以全域性使用。
Map<Integer, Integer> map = new HashMap<Integer, Integer>(); public boolean isHappy(int n) { if (n <= 0) { return false; } if (n == 1) { return true; } int index = 1; int sum = 0; for (int i=0; i <(n+"").length(); i++) { sum += Math.pow((n+"").charAt(i)-'0', 2); } if (sum == 1) { return true; } if (map.containsKey(sum)) { return false; } else { map.put(sum, index++); } return isHappy(sum); }
03 第二種解法
思路與上面一樣,不過使用的是迭代的方法,所以,定義的HashMap放在你方法裡面。使用了兩層迴圈,外層控制map判斷key是否存在以及替換新的n,內層迴圈處理新數不同位整數的平方和。
public boolean isHappy2(int n) { if (n <= 0) { return false; } if (n == 1) { return true; } Map<Integer, Integer> map2 = new HashMap<Integer, Integer>(); int index = 1; int sum = 0; while (true) { for (int i=0; i <(n+"").length(); i++) { sum += Math.pow((n+"").charAt(i)-'0', 2); } if (sum == 1) { return true; } if (map2.containsKey(sum)) { return false; } else { map2.put(sum, index++); } n = sum; sum = 0; } }
04 第三種解法
如果你算過幾個特殊的數,比如2、4、14、16、18,這些數字都會陷入死迴圈,並且是數字4.至於其他的數,如果不是幸福數,都會陷入死迴圈裡面,死迴圈的入口就是4或者16,對此,我們可以不使用HashMap,只要判斷新得到的數是否等於4或者16即可表示此數字不是幸福數字。
此解法同樣是使用迭代的方法,藉助兩層迴圈,外層做判斷,內層做不同位數字的平方和。
public boolean isHappy3(int n) { int sum = 0; while (sum != 1) { if (n == 4 || n == 16) break; while (n > 0) { int rem = n % 10; sum += rem * rem; n /= 10; } if (sum == 1) return true; n = sum; sum = 0; } return false; }
05 第四種解法
使用HashSet,藉助其不能存在重複元素的特性,思路和第一、第二種解法一樣,都是先去獲取新數的平方和,然後新增進HashSet,如果新增失敗,說明已經存在該整數,即不是幸福數。不過這裡是改變了n的原始值,所以最後判斷的是n是否等於1。
public boolean isHappy4(int n) { HashSet<Integer> seen = new HashSet<>(); while (seen.add(n)) { int square = 0; int sum = 0; while (n!=0) { square = n%10; sum += (square*square); n /=10; } n = sum; } return n==1 ? true : false; }
06 第五種解法
藉助環的思路。如果你還對之前的判斷一個連結串列是否存在環的那道題目有印象的話,那麼此題是與之類似的,每次新得到的數就代表一個節點,如果此節點出現過一次,即表示此連結串列是有環的,也就是說明此數是幸福數。
藉助雙指標,一個每次進行一次計算,另外一個每次計算兩次,相當於速度是前一個的兩倍,如果存在相同的數,兩個指標肯定會相遇。
public boolean isHappy5(int n) { int slow = n; int fast = n; do { slow = digitSquareSum(slow); fast = digitSquareSum(fast); fast = digitSquareSum(fast); if (slow == 1 || fast == 1) { return true; } } while(slow != fast); return false; } public int digitSquareSum(int n) { int sum = 0, tmp; while (n > 0) { tmp = n % 10; sum += tmp * tmp; n /= 10; } return sum; }
07 小結
演算法專題目前已連續日更超過一個月,演算法題文章47 +篇,公眾號對話方塊回覆【資料結構與演算法 】、【演算法 】、【資料結構 】中的任一關鍵詞,獲取系列文章合集。
以上就是全部內容,如果大家有什麼好的解法思路、建議或者其他問題,可以下方留言交流,點贊、留言、轉發就是對我最大的回報和支援!