Q202 Happy Number

weixin_34007291發表於2018-02-28

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: 19 is a happy number

12 + 92 = 82
82 + 22 = 68
62 + 82 = 100
12 + 02 + 02 = 1
解題思路:

根據題意,最後結果為 1 是 happy number,返回 True,否則必定出現環,不是 happy number 返回 False。

在寫程式碼的時候,happy number 的終止條件容易得到(迴圈過程中平方和等於1即可)。但是,不是 happy number 的終止條件不容易找到。

但是,發現一個規律:如果出現環,則這個環中必定出現 4 這個數字。比如5,迴圈結果依次是:

25,29,85,89,145,42,20,4,16,37,58,89,145,42,20,4......

其他不是 happy number 的也有這樣的規律。因此,迴圈終止的條件就可以找到了。

Python實現:
class Solution(object):
    def isHappy(self, n):
        """
        :type n: int
        :rtype: bool
        """
        while True:
            n = sum([int(ch)**2 for ch in str(n)])
            if n == 1: return True
            if n == 4: return False

a = 19
b = 8
c = Solution()
print(c.isHappy(a))  # True
print(c.isHappy(b))  # False
補充:

如果觀察不到這個規律,我可能使用快慢指標解決是否有環的問題。慢指標 slow 每次只計算一次平方和,快指標 fast 每次計算兩次平方和。如果快指標追上慢指標(fast = slow),且慢指標不為1,則代表有環,不是 happy number,否則為 happy number。

快慢指標的思路來源於判斷連結串列是否有環的問題:Q141 Linked List Cycle

關於快慢指標:

快慢指標可以解決這樣的問題:

  1. 判斷連結串列是否有環(設定兩個指標,慢指標每次走一步,快指標每次走兩步,如果有環,兩指標總會相遇);
  2. 求連結串列中點(設定兩個指標,慢指標每次走一步,快指標每次走兩步,當快指標走到連結串列尾,慢指標剛好到連結串列中點);
  3. 求連結串列倒數第n個數(設定兩個指標,快指標先走n步,然後慢指標和快指標一起走,當快指標到達連結串列尾,慢指標剛好為倒數第n個數);
  4. 如果連結串列有環,求環的入口(設定兩個指標,一個指標指向相遇點,一個指標指向連結串列頭。每次各走一步,再次相遇的點就是環入口)。

相關文章