Given a positive integer num, return true
if num
is a perfect square or false
otherwise.
A perfect square is an integer that is the square of an integer. In other words, it is the product of some integer with itself.
You must not use any built-in library function, such as sqrt
.
Example 1:
Input: num = 16 Output: true Explanation: We return true because 4 * 4 = 16 and 4 is an integer.
Example 2:
Input: num = 14 Output: false Explanation: We return false because 3.742 * 3.742 = 14 and 3.742 is not an integer.
Constraints:
1 <= num <= 231 - 1
When you get asked this question in a real-life environment, it will often be ambiguous (especially at FAANG). Make sure to ask these questions in that case:
To check if a number is a perfect square using the brute force strategy, we can try multiplying numbers by themselves. We'll start with a small number and keep increasing it, checking if the square of that number matches the given number.
Here's how the algorithm would work step-by-step:
def is_valid_perfect_square(number) -> bool:
current_number = 1
while True:
square = current_number * current_number
# If the square is equal to the number, we found a perfect square
if square == number:
return True
#If the square is greater than the number, it can't be a perfect square
if square > number:
return False
#Increment and try the next number
current_number += 1
Instead of checking every number, the best way to find out if a number is a perfect square is to use a guessing game that quickly narrows down the possibilities. It's like playing 'higher or lower' to find the square root without calculating every square.
Here's how the algorithm would work step-by-step:
def is_perfect_square(number) -> bool:
if number < 0:
return False
low_range = 0
high_range = number
while low_range <= high_range:
potential_root = (low_range + high_range) // 2
square_of_potential_root = potential_root * potential_root
if square_of_potential_root == number:
return True
elif square_of_potential_root < number:
# Guess was too low, increase lower bound.
low_range = potential_root + 1
else:
# Guess was too high, decrease higher bound.
high_range = potential_root - 1
#If low > high, then the number is not a perfect square
return False
Case | How to Handle |
---|---|
Input is zero | Return true since 0 * 0 = 0 |
Input is a negative number | Return false as perfect squares are non-negative |
Input is 1 | Return true since 1 * 1 = 1 |
Input is the maximum possible integer | The chosen algorithm (binary search) should handle this case gracefully by adjusting the range accordingly, but integer overflow could be a concern in other approaches requiring multiplication. |
Square root exceeds the maximum integer representable in the language (potential overflow) | Use long or a larger data type to perform the square calculation to prevent overflow, or use division to check. |
Input is a large perfect square (e.g., close to the maximum integer) | Binary search should converge correctly and efficiently find the integer square root without significant performance issues. |
Input is a number that is close to a perfect square but isn't one | Binary search needs to check precisely after convergence whether square of mid equals the input. |
Very large input numbers that require a large range for the binary search. | Binary search implementation handles this automatically by dynamically adjusting search space ensuring logarithmic time complexity. |