TARGET DECK: Leetcode FILE TAGS: Easy
Intuition
- A digit will eventually loop back to become itself.
- That is to say: The following property holds:
- If a digit’s squares is multiplied by itself enough times, then eventually, you will get the sum equal to 1. Otherwise, it will eventually loop back to become a number “unto itself”.
- The question then is: why?
- To understand this, take the largest possible digit. For example, 9, 99, 999, etc.
- Notice that is 81. Therefore, in the one’s place, any digit smaller than 9 will be at most 81, or some number less than 81. So there are 2 options: Either loop back to some number from 2, to 81, or stop at 1.
- The Floyds Tortoise and Hare algorithm also works here, wherein you utilize the fact that you loop forever at 1 when you have indeed reached 1, since is always 1, so slow the slow pointer will always eventually catch up to fast.
Info
With this question and others like it, it helps visualizing the entire example, since for example with n = 2, you would have found out the answer if you just kept repeating numbers until the number equaled itself again.
Complexity
Runtime
- For
getNext(): since you are dividing by 10 each time, and so you are doing that = N times, meaning N = . - You repeat getNext() a constant number of times (from 4→16→37→58→89→145→42→20→4).
Space
if using Floyds Tortoise and Hare algorithm due to no HashSet.
Code
Using Floyds Tortoise and Hare for Cycle Detection
class Solution:
def getSquareSum(self, num):
cur_sum = 0
while num > 0:
num, digit = divmod(num, 10)
cur_sum += digit ** 2
return cur_sum
def isHappy(self, n: int) -> bool:
slow = fast = n
while True:
slow = self.getSquareSum(slow)
fast = self.getSquareSum(self.getSquareSum(fast))
if slow == fast:
break
return slow == 1Using Divmod
class Solution:
def getNext(self, num):
cur_sum = 0
while num > 0:
num, digit = divmod(num, 10)
cur_sum += digit ** 2
return cur_sum
def isHappy(self, n: int) -> bool:
while n != 1 and n != 4:
n = self.getNext(n)
return n == 1Using Modulo Arithmetic Instead
class Solution:
def getNext(self, num):
cur_sum = 0
while num > 0:
num, digit = num // 10, num % 10
cur_sum += digit ** 2
return cur_sum
def isHappy(self, n: int) -> bool:
while n != 1 and n != 4:
n = self.getNext(n)
return n == 1- Works since // truncates, and % gets the last digit.
- Alternatively, can probably use Bit Manipulation.
Using Trick: Any Number that is in a Cycle Will Eventually Cycle Back to 4
class Solution:
def isHappy(self, n: int) -> bool:
while n != 1 and n != 4:
n = sum(int(digit) ** 2 for digit in str(n))
return n == 1Using HashSet to Store Cycle, and String Set
class Solution:
def isHappy(self, n: int) -> bool:
visited = set()
while n not in visited:
visited.add(n)
n = sum(int(digit) ** 2 for digit in str(n))
return n == 1Notes
Cards
START Basic Front: Happy Number Back: A number that is squared will always repeat forever, and from 4 → 16 → 37 → 58 → 89 → 145 → 42 → 20 → 4
END
