Created
October 31, 2018 21:50
-
-
Save adnauseum/7dc8dcba5b45086be48f674d75fe3419 to your computer and use it in GitHub Desktop.
Integer Palindrome
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Solution: | |
def isPalindrome(self, user_supplied_integer): | |
""" | |
In order to avoid string conversion, the algorithm hinges on some math tricks. But it | |
prevents the inevitable O(n) of int-to-string conversion. Instead we can do what we | |
need to in O(n/2), though this is often expressed as O(n), it is still better! | |
Let's say your function is given the following int argument: 35753 | |
First, | |
You can obtain the length of the user_supplied_integer with: | |
num_digits = math.floor(math.log10(x)) + 1 | |
The length of the digit is important for knowing how long you should loop for. With the | |
above argument, num_digits will be 5.0. | |
Second, | |
You can use a "mask" to obtain the number in the front: | |
msd_mask = 10**(num_digits - 1) | |
first_digit = user_supplied_integer // msd_mask | |
In our above input, the `msd_mask` will be: 10000.0 which represents the highest decimal | |
place value on the left on the decimal (35753.0, for instance). Now you can see how we get | |
the first digit: `35753 // 10000.0` will yield `3.0`. Recall that `/` will give us 3.5753. | |
Third, | |
You can use `% 10` to obtain the number in the back: | |
last_digit = user_supplied_integer % 10 | |
Basically, you are asking, what is the largest multiple of 35753 and 10? Well 10 * 3575 is | |
35750. 35753 - 35750 is 3. That's the last digit. Doing % 10 will always give us the last digit. | |
To get a better understanding of modulus division, check out: https://youtu.be/akfFEj7oTn0 | |
You now have all that you need. With each iteration we can simulate having a "front pointer" | |
and a "back pointer" to check equality. Because we check two at a time, we don't have to run | |
once for each digit. We can run once for every two digits, hence: | |
`for i in range(num_digits // 2)` | |
Check if the front is equal to the digit in the back. If they are not, return false. If they | |
are the same, you'll actually be removing the front digit and the back digit. | |
After each iteration you'll need to remove the first and last digit from the | |
user_supplied_integer so that you can keep comparing numbers. You can do this by: | |
1) Remove the most significant digit by modulo-ing off the number in the highest tens place | |
user_supplied_integer %= msd_mask | |
Recall, what is the largest multiple of 35753 and our msd_mask, 10000? 10000 * 3 is 30000 | |
which gives us a remainder of 5753. This is equivalent to removing the first digit in the | |
user_supplied_integer. | |
Removing the least significant digit by removing the number in the tens place by dividing | |
the integer by ten | |
user_supplied_integer //= 10 | |
Finally, you have to shorten your msd_mask to reflect the integer you just clipped | |
(on both ends). | |
msd_mask //= 100 | |
The `100` has two zeros--that is the number of zeroes you'll remove from your msd_mask. | |
If your msd_mask was 10000, it'll now become 100--that is, with the final two zeroes removed. | |
Repeat! | |
:type user_supplied_integer: int | |
:rtype: bool | |
""" | |
if user_supplied_integer < 0: | |
return False | |
if user_supplied_integer < 2: | |
return True | |
num_digits = math.floor(math.log10(user_supplied_integer)) + 1 | |
msd_mask = 10**(num_digits - 1) | |
for i in range(num_digits // 2): | |
first_digit = user_supplied_integer // msd_mask | |
last_digit = user_supplied_integer % 10 | |
if first_digit != last_digit: | |
# We don't have a palindrome | |
return False | |
# Remove the most significant digit (front) | |
user_supplied_integer %= msd_mask | |
# Remove the least significant digit (back) | |
user_supplied_integer //= 10 | |
# Shorten the msd_mask to match the current user_supplied_integer | |
msd_mask //= 100 | |
return True |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment