Valid Perfect Square - Complete Solution Guide
Valid Perfect Square is LeetCode problem 367, a Easy level challenge. This complete guide provides step-by-step explanations, multiple solution approaches, and optimized code in python3, java, cpp, c.
Problem Statement
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 n
Detailed Explanation
The problem asks us to determine if a given positive integer `num` is a perfect square. A perfect square is an integer that can be obtained by squaring another integer. For instance, 16 is a perfect square because 4 * 4 = 16. We need to solve this without using any built-in square root functions.
Solution Approach
The provided solutions employ a binary search algorithm to efficiently search for a potential integer root of the given number. The algorithm narrows down the search space by repeatedly dividing the interval in half. The Python, Java and C++ solutions utilize a standard binary search implementation. The C version instead uses a linear, incremental search.
Step-by-Step Algorithm
- Step 1: Initialize `low` to 1 and `high` to `num`. These represent the lower and upper bounds of our search space for the potential integer root.
- Step 2: While `low` is less than or equal to `high`, calculate the middle value `mid` as `(low + high) // 2` (or `left + (right - left) / 2` in Java/C++ to prevent potential overflow).
- Step 3: Calculate the square of `mid` as `square = mid * mid`.
- Step 4: Compare `square` with `num`:
- Step 5: If `square` is equal to `num`, then `num` is a perfect square, so return `True`.
- Step 6: If `square` is less than `num`, then the potential root is larger, so update `low` to `mid + 1`.
- Step 7: If `square` is greater than `num`, then the potential root is smaller, so update `high` to `mid - 1`.
- Step 8: If the loop finishes without finding a perfect square (i.e., `low` becomes greater than `high`), then `num` is not a perfect square, so return `False`.
Key Insights
- Insight 1: Binary search can efficiently find the potential integer root because the range of possible roots is from 1 to num.
- Insight 2: The square of the potential root can quickly become large, exceeding the integer limit. Thus, it is better to use long datatype in languages like Java and C++ to avoid integer overflow during the multiplication.
- Insight 3: Integer division (// in Python, division in Java/C++) truncates, so mid can only ever be an integer. This is critical to the approach working.
- Insight 4: In the C solution, it uses an incremental search. While easier to understand, it's less efficient than binary search for larger numbers. Using `long long` is essential to avoid overflow.
Complexity Analysis
Time Complexity: O(log n)
Space Complexity: O(1)
Topics
This problem involves: Math, Binary Search.
Companies
Asked at: LinkedIn, SAP.