633. Sum of Square Numbers
Problem Description
You are given a non-negative integer c
. Your task is to determine whether there exist two integers a
and b
such that a² + b² = c
.
In other words, you need to check if the given number c
can be expressed as the sum of two perfect squares. The integers a
and b
can be any non-negative integers, including zero.
For example:
- If
c = 5
, the answer istrue
because1² + 2² = 1 + 4 = 5
- If
c = 3
, the answer isfalse
because there are no two integers whose squares sum to 3
The solution uses a two-pointer technique. It starts with a = 0
and b = √c
(rounded down to the nearest integer). Then it checks if a² + b²
equals c
. If the sum is less than c
, it increases a
. If the sum is greater than c
, it decreases b
. This process continues until either a valid pair is found or a
becomes greater than b
, indicating no such pair exists.
Intuition
The key insight is that if c
can be expressed as a² + b²
, then both a
and b
must be at most √c
. Why? Because if either value exceeds √c
, then that value squared alone would be greater than c
, making it impossible for the sum to equal c
.
This gives us a bounded search space: a
can range from 0
to √c
, and similarly for b
. However, checking all possible pairs would be inefficient.
Here's where the two-pointer technique becomes clever. We start with a = 0
(the minimum possible value) and b = √c
(the maximum possible value). At each step, we calculate a² + b²
:
- If the sum equals
c
, we've found our answer - If the sum is less than
c
, we need to make it larger. Sinceb
is already at its maximum useful value for the currenta
, we increasea
- If the sum is greater than
c
, we need to make it smaller, so we decreaseb
This approach works because as we adjust the pointers, we systematically explore all potentially valid combinations. The beauty is that we never miss a valid pair - if we skip over some combination, it's because we've already determined it cannot possibly sum to c
based on our current bounds.
The algorithm terminates when either we find a valid pair or when a > b
, which means we've exhausted all possibilities. The condition a <= b
is sufficient because if a valid pair (a, b)
exists with a > b
, then the pair (b, a)
would also be valid and would have been checked earlier when b > a
.
Learn more about Math, Two Pointers and Binary Search patterns.
Solution Approach
The implementation uses the two-pointer technique with mathematical bounds to efficiently search for valid pairs.
Step 1: Initialize the pointers
- Set
a = 0
as the left pointer (minimum value) - Set
b = int(sqrt(c))
as the right pointer (maximum possible value)
Step 2: Search using two pointers
While a <= b
, perform the following:
-
Calculate the sum
s = a² + b²
-
Compare
s
with target valuec
:- If
s == c
: We've found a valid pair, returnTrue
- If
s < c
: The current sum is too small, so incrementa
by 1 to increase the sum - If
s > c
: The current sum is too large, so decrementb
by 1 to decrease the sum
- If
Step 3: Return result
If the loop completes without finding a valid pair (when a > b
), return False
.
Why this works:
The algorithm systematically explores the solution space by adjusting pointers based on the comparison result. Starting from the extremes (0
and √c
), we narrow down the search range:
- When we increase
a
, we're exploring larger values for the smaller component - When we decrease
b
, we're exploring smaller values for the larger component - The condition
a <= b
ensures we don't check duplicate pairs (sincea² + b² = b² + a²
)
Time Complexity: O(√c)
- In the worst case, we might need to move the pointers through all values from 0
to √c
.
Space Complexity: O(1)
- We only use a constant amount of extra space for the two pointers and the sum variable.
Ready to land your dream job?
Unlock your dream job with a 5-minute evaluator for a personalized learning plan!
Start EvaluatorExample Walkthrough
Let's walk through the algorithm with c = 13
to see how the two-pointer technique finds that 13 = 2² + 3²
.
Initial Setup:
a = 0
(left pointer starts at minimum)b = √13 = 3
(right pointer starts at maximum, rounded down)
Iteration 1:
- Calculate:
a² + b² = 0² + 3² = 0 + 9 = 9
- Compare:
9 < 13
(sum is too small) - Action: Increment
a
to1
Iteration 2:
- Calculate:
a² + b² = 1² + 3² = 1 + 9 = 10
- Compare:
10 < 13
(sum is still too small) - Action: Increment
a
to2
Iteration 3:
- Calculate:
a² + b² = 2² + 3² = 4 + 9 = 13
- Compare:
13 == 13
(found exact match!) - Action: Return
True
The algorithm successfully finds that 13
can be expressed as 2² + 3²
.
Let's also see an example where no solution exists with c = 3
:
Initial Setup:
a = 0
(left pointer)b = √3 = 1
(right pointer, rounded down)
Iteration 1:
- Calculate:
a² + b² = 0² + 1² = 0 + 1 = 1
- Compare:
1 < 3
(sum is too small) - Action: Increment
a
to1
Iteration 2:
- Calculate:
a² + b² = 1² + 1² = 1 + 1 = 2
- Compare:
2 < 3
(sum is still too small) - Action: Increment
a
to2
Check loop condition:
- Now
a = 2
andb = 1
, soa > b
- Loop terminates, return
False
The algorithm correctly determines that 3
cannot be expressed as the sum of two perfect squares.
Solution Implementation
1import math
2
3class Solution:
4 def judgeSquareSum(self, c: int) -> bool:
5 """
6 Check if a non-negative integer c can be expressed as the sum of two squares.
7 Uses two-pointer approach to find if there exist integers a and b such that a² + b² = c.
8
9 Args:
10 c: Non-negative integer to check
11
12 Returns:
13 True if c can be expressed as sum of two squares, False otherwise
14 """
15 # Initialize left pointer at 0 and right pointer at square root of c
16 left = 0
17 right = int(math.sqrt(c))
18
19 # Use two pointers to search for valid pair
20 while left <= right:
21 # Calculate sum of squares of current pair
22 current_sum = left * left + right * right
23
24 if current_sum == c:
25 # Found valid pair (a, b) where a² + b² = c
26 return True
27 elif current_sum < c:
28 # Sum is too small, increase left pointer
29 left += 1
30 else:
31 # Sum is too large, decrease right pointer
32 right -= 1
33
34 # No valid pair found
35 return False
36
1class Solution {
2 /**
3 * Determines if a non-negative integer c can be expressed as the sum of two squares.
4 * Uses two-pointer technique to find if there exist integers a and b such that a² + b² = c.
5 *
6 * @param c the target non-negative integer to check
7 * @return true if c can be expressed as sum of two squares, false otherwise
8 */
9 public boolean judgeSquareSum(int c) {
10 // Initialize left pointer starting from 0
11 long left = 0;
12
13 // Initialize right pointer starting from the square root of c (maximum possible value)
14 long right = (long) Math.sqrt(c);
15
16 // Use two-pointer approach to search for valid pair
17 while (left <= right) {
18 // Calculate the sum of squares of current pair
19 long sumOfSquares = left * left + right * right;
20
21 // Check if we found the exact sum
22 if (sumOfSquares == c) {
23 return true;
24 }
25
26 // If sum is less than target, increase left pointer to get larger sum
27 if (sumOfSquares < c) {
28 left++;
29 }
30 // If sum is greater than target, decrease right pointer to get smaller sum
31 else {
32 right--;
33 }
34 }
35
36 // No valid pair found
37 return false;
38 }
39}
40
1class Solution {
2public:
3 bool judgeSquareSum(int c) {
4 // Use long long to prevent integer overflow when calculating squares
5 long long left = 0;
6 long long right = static_cast<long long>(sqrt(c));
7
8 // Two-pointer approach: left starts from 0, right starts from sqrt(c)
9 while (left <= right) {
10 // Calculate the sum of squares of current pointers
11 long long sumOfSquares = left * left + right * right;
12
13 // Check if we found a valid pair
14 if (sumOfSquares == c) {
15 return true;
16 }
17
18 // If sum is less than target, increase left pointer to get larger sum
19 if (sumOfSquares < c) {
20 ++left;
21 }
22 // If sum is greater than target, decrease right pointer to get smaller sum
23 else {
24 --right;
25 }
26 }
27
28 // No valid pair found
29 return false;
30 }
31};
32
1/**
2 * Determines if a non-negative integer c can be expressed as the sum of two squares
3 * Uses two-pointer technique to find if there exist integers a and b such that a² + b² = c
4 *
5 * @param c - The target non-negative integer to check
6 * @returns true if c can be expressed as sum of two squares, false otherwise
7 */
8function judgeSquareSum(c: number): boolean {
9 // Initialize two pointers:
10 // left starts at 0 (minimum possible value)
11 // right starts at the square root of c (maximum possible value for b)
12 let left: number = 0;
13 let right: number = Math.floor(Math.sqrt(c));
14
15 // Use two-pointer approach to search for valid pair
16 while (left <= right) {
17 // Calculate the sum of squares of current pair
18 const sumOfSquares: number = left * left + right * right;
19
20 if (sumOfSquares === c) {
21 // Found a valid pair where a² + b² = c
22 return true;
23 } else if (sumOfSquares < c) {
24 // Sum is too small, increase left pointer to get larger sum
25 left++;
26 } else {
27 // Sum is too large, decrease right pointer to get smaller sum
28 right--;
29 }
30 }
31
32 // No valid pair found
33 return false;
34}
35
Time and Space Complexity
The time complexity is O(√c)
, where c
is the given non-negative integer. This is because the algorithm uses a two-pointer approach where a
starts at 0 and b
starts at int(sqrt(c))
. In each iteration of the while loop, either a
is incremented or b
is decremented, moving the pointers closer together. The loop terminates when a > b
. Since a
can increase from 0 to at most √c
and b
can decrease from √c
to 0, the total number of iterations is bounded by O(√c)
.
The space complexity is O(1)
as the algorithm only uses a constant amount of extra space for the variables a
, b
, and s
, regardless of the input size.
Learn more about how to find time and space complexity quickly.
Common Pitfalls
1. Integer Overflow When Calculating Squares
The Problem:
When calculating left * left + right * right
, the intermediate values can cause integer overflow for large values of c
. Even though Python handles arbitrary precision integers automatically, in languages like Java or C++, computing a² + b²
directly can overflow when c
is near the maximum integer value.
Example of the Issue:
# In languages with fixed integer sizes: # If c = 2^31 - 1 (max int), and right = sqrt(c) ≈ 46340 # Then right * right could overflow before the comparison
Solution: Instead of computing the sum and comparing, rearrange the comparison to avoid overflow:
import math
class Solution:
def judgeSquareSum(self, c: int) -> bool:
left = 0
right = int(math.sqrt(c))
while left <= right:
# Avoid direct sum calculation to prevent overflow
left_square = left * left
right_square = right * right
# Check if calculation would overflow (for other languages)
# In Python, we can still use this safer approach
if left_square > c - right_square:
right -= 1
elif left_square < c - right_square:
left += 1
else:
return True
return False
2. Incorrect Square Root Calculation
The Problem:
Using floating-point square root without proper conversion to integer can lead to precision errors. For example, sqrt(c)
might return a value slightly less than the actual integer square root due to floating-point representation.
Example of the Issue:
# Potential precision issue import math c = 4 right = math.sqrt(c) # Returns 2.0 (float) # If not handled properly, comparisons might fail
Solution:
Always use int(math.sqrt(c))
or math.isqrt(c)
(Python 3.8+) for exact integer square root:
import math
class Solution:
def judgeSquareSum(self, c: int) -> bool:
left = 0
# Use math.isqrt for exact integer square root (Python 3.8+)
# or int(math.sqrt(c)) for earlier versions
right = math.isqrt(c) if hasattr(math, 'isqrt') else int(math.sqrt(c))
while left <= right:
current_sum = left * left + right * right
if current_sum == c:
return True
elif current_sum < c:
left += 1
else:
right -= 1
return False
3. Missing Edge Case: c = 0
The Problem:
Not handling the special case where c = 0
, which should return True
since 0² + 0² = 0
.
Solution:
The current implementation handles this correctly since when c = 0
, both left
and right
start at 0, and 0 + 0 = 0
returns True
. However, it's good practice to be aware of this edge case and potentially add an early return for clarity:
class Solution:
def judgeSquareSum(self, c: int) -> bool:
# Early return for edge case
if c == 0:
return True
left = 0
right = int(math.sqrt(c))
while left <= right:
current_sum = left * left + right * right
if current_sum == c:
return True
elif current_sum < c:
left += 1
else:
right -= 1
return False
Given a sorted array of integers and an integer called target, find the element that
equals to the target and return its index. Select the correct code that fills the
___
in the given code snippet.
1def binary_search(arr, target):
2 left, right = 0, len(arr) - 1
3 while left ___ right:
4 mid = (left + right) // 2
5 if arr[mid] == target:
6 return mid
7 if arr[mid] < target:
8 ___ = mid + 1
9 else:
10 ___ = mid - 1
11 return -1
12
1public static int binarySearch(int[] arr, int target) {
2 int left = 0;
3 int right = arr.length - 1;
4
5 while (left ___ right) {
6 int mid = left + (right - left) / 2;
7 if (arr[mid] == target) return mid;
8 if (arr[mid] < target) {
9 ___ = mid + 1;
10 } else {
11 ___ = mid - 1;
12 }
13 }
14 return -1;
15}
16
1function binarySearch(arr, target) {
2 let left = 0;
3 let right = arr.length - 1;
4
5 while (left ___ right) {
6 let mid = left + Math.trunc((right - left) / 2);
7 if (arr[mid] == target) return mid;
8 if (arr[mid] < target) {
9 ___ = mid + 1;
10 } else {
11 ___ = mid - 1;
12 }
13 }
14 return -1;
15}
16
Recommended Readings
Math for Technical Interviews How much math do I need to know for technical interviews The short answer is about high school level math Computer science is often associated with math and some universities even place their computer science department under the math faculty However the reality is that you
Tech Interview Pattern Two Pointers Introduction If you prefer videos here's a super quick introduction to Two Pointers div class responsive iframe iframe src https www youtube com embed xZ4AfXHQ1VQ title YouTube video player frameborder 0 allow accelerometer autoplay clipboard write encrypted media gyroscope picture in picture allowfullscreen iframe div Two pointers is a common interview
Binary Search Speedrun For each of the Speedrun questions you will be given a binary search related problem and a corresponding multiple choice question The multiple choice questions are related to the techniques and template s introduced in the binary search section It's recommended that you have gone through at
Want a Structured Path to Master System Design Too? Don’t Miss This!