1237. Find Positive Integer Solution for a Given Equation
Problem Description
You are given a callable function f(x, y) with a hidden formula and a target value z. Your task is to find all positive integer pairs (x, y) such that f(x, y) == z.
The function f(x, y) has the following properties:
- It takes two positive integers
xandyas inputs - It returns a positive integer based on a hidden formula
- It is monotonically increasing in both parameters:
f(x, y) < f(x + 1, y)(increasing with respect tox)f(x, y) < f(x, y + 1)(increasing with respect toy)
You need to implement a findSolution method that:
- Takes a
CustomFunctionobject and an integerzas parameters - Returns a list of all
[x, y]pairs wheref(x, y) == z - The pairs can be returned in any order
- Both
xandymust be positive integers
The solution approach leverages the monotonic property of the function. Since f(x, y) is increasing in both dimensions, for each value of x from 1 to z, we can use binary search to find if there exists a y value such that f(x, y) == z. The binary search is performed on the range [1, z] for y, using the function value f(x, y) as the comparison key. If a valid y is found for a given x, the pair [x, y] is added to the result list.
Intuition
The key insight comes from understanding the monotonic property of the function. Since f(x, y) increases as either x or y increases, we can think of the function values as forming a 2D grid where values grow both rightward and upward.
Imagine we fix x at some value. As y increases from 1 onwards, f(x, y) will produce an increasing sequence of values. At some point, this sequence might contain our target z, or it might skip over it entirely. Because the sequence is sorted, we can efficiently search for z using binary search instead of checking every possible y value.
Why enumerate x and binary search y? We could do it either way, but we need to fix one variable to create a one-dimensional sorted sequence that we can binary search. By iterating through all possible x values from 1 to z, we ensure we don't miss any valid pairs.
Why can we limit both x and y to the range [1, z]? Since f(x, y) is monotonically increasing and both x and y are positive integers starting from 1, the minimum possible value is f(1, 1). If f(1, 1) ≤ z, then for any x > z or y > z, we would have f(x, 1) > f(z, 1) ≥ f(1, 1) ≥ z or similarly for y. This means f(x, y) would definitely exceed z when either parameter is greater than z.
The binary search finds the leftmost position where f(x, y) >= z. If the function value at that position equals z, we've found a valid pair. If it's greater than z, it means no y value for this particular x gives us exactly z.
Learn more about Math, Two Pointers and Binary Search patterns.
Solution Approach
The implementation uses enumeration combined with binary search to efficiently find all valid pairs.
Step-by-step implementation:
-
Initialize the result list: Create an empty list
ansto store all valid[x, y]pairs. -
Enumerate x values: Loop through all possible
xvalues from1toz:for x in range(1, z + 1): -
Binary search for y: For each fixed
x, use binary search to find ayvalue wheref(x, y) = z. The code uses Python'sbisect_leftfunction with a custom key:y = 1 + bisect_left( range(1, z + 1), z, key=lambda y: customfunction.f(x, y) )Here's what happens:
range(1, z + 1)creates the search space foryvaluesbisect_leftsearches for the leftmost position where we could insertzto maintain sorted orderkey=lambda y: customfunction.f(x, y)tells the binary search to compare based on function values, not theyvalues themselves- We add
1to the result becausebisect_leftreturns an index (0-based) but ouryvalues start from1
-
Check if exact match found: After binary search, verify if the found position gives us exactly
z:if customfunction.f(x, y) == z: ans.append([x, y])The binary search finds where
f(x, y) >= z. Iff(x, y) == z, we have a valid pair. Iff(x, y) > z, it means noyvalue for thisxproduces exactlyz. -
Return all pairs: After checking all possible
xvalues, return the collected pairs.
Time Complexity: O(z * log z) - We iterate through z values of x, and for each x, we perform a binary search over at most z values of y.
Space Complexity: O(1) if we don't count the output array, as we only use a constant amount of extra space for variables.
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 a concrete example where we have a hidden function and need to find all pairs (x, y) where f(x, y) = 5.
Suppose the hidden function is f(x, y) = x + y (we don't know this, but it helps visualize the process).
Target: z = 5
We'll iterate through x values from 1 to 5 and use binary search to find corresponding y values:
When x = 1:
- We binary search for y in range [1, 5] where f(1, y) = 5
- Binary search process:
- Check middle: y = 3, f(1, 3) = 4 < 5 (go right)
- Check y = 4, f(1, 4) = 5 = 5 ✓
- Found pair: [1, 4]
When x = 2:
- Binary search for y in range [1, 5] where f(2, y) = 5
- Binary search process:
- Check middle: y = 3, f(2, 3) = 5 = 5 ✓
- Found pair: [2, 3]
When x = 3:
- Binary search for y in range [1, 5] where f(3, y) = 5
- Binary search process:
- Check middle: y = 3, f(3, 3) = 6 > 5 (go left)
- Check y = 1, f(3, 1) = 4 < 5 (go right)
- Check y = 2, f(3, 2) = 5 = 5 ✓
- Found pair: [3, 2]
When x = 4:
- Binary search for y in range [1, 5] where f(4, y) = 5
- Binary search process:
- Check middle: y = 3, f(4, 3) = 7 > 5 (go left)
- Check y = 1, f(4, 1) = 5 = 5 ✓
- Found pair: [4, 1]
When x = 5:
- Binary search for y in range [1, 5] where f(5, y) = 5
- Binary search process:
- Check middle: y = 3, f(5, 3) = 8 > 5 (go left)
- Check y = 1, f(5, 1) = 6 > 5 (go left further)
- No valid y exists (all values > 5)
- No pair found
Result: [[1, 4], [2, 3], [3, 2], [4, 1]]
The key insight is that for each fixed x, the function values f(x, 1), f(x, 2), f(x, 3)... form an increasing sequence, allowing us to efficiently binary search for the target value rather than checking every possibility.
Solution Implementation
1from typing import List
2from bisect import bisect_left
3
4
5class Solution:
6 def findSolution(self, customfunction: 'CustomFunction', z: int) -> List[List[int]]:
7 """
8 Find all pairs [x, y] where customfunction.f(x, y) == z.
9
10 Since f(x, y) is strictly increasing with respect to both x and y,
11 we can use binary search to find valid y values for each x.
12
13 Args:
14 customfunction: Custom function object with method f(x, y)
15 z: Target value to find
16
17 Returns:
18 List of [x, y] pairs where f(x, y) == z
19 """
20 result = []
21
22 # Try each possible x value from 1 to z
23 for x in range(1, z + 1):
24 # Binary search for y where f(x, y) == z
25 # Since f is increasing, we search in range [1, z]
26 left, right = 1, z
27
28 while left <= right:
29 mid = (left + right) // 2
30 current_value = customfunction.f(x, mid)
31
32 if current_value == z:
33 # Found a valid pair
34 result.append([x, mid])
35 break
36 elif current_value < z:
37 # Need larger y value
38 left = mid + 1
39 else:
40 # Need smaller y value
41 right = mid - 1
42
43 return result
441/*
2 * // This is the custom function interface.
3 * // You should not implement it, or speculate about its implementation
4 * class CustomFunction {
5 * // Returns f(x, y) for any given positive integers x and y.
6 * // Note that f(x, y) is increasing with respect to both x and y.
7 * // i.e. f(x, y) < f(x + 1, y), f(x, y) < f(x, y + 1)
8 * public int f(int x, int y);
9 * };
10 */
11
12class Solution {
13 public List<List<Integer>> findSolution(CustomFunction customfunction, int z) {
14 // List to store all pairs (x, y) where f(x, y) = z
15 List<List<Integer>> result = new ArrayList<>();
16
17 // Iterate through all possible x values from 1 to 1000
18 for (int x = 1; x <= 1000; x++) {
19 // Use binary search to find y such that f(x, y) = z
20 int left = 1;
21 int right = 1000;
22
23 // Binary search for the target y value
24 while (left < right) {
25 int mid = (left + right) / 2;
26
27 // Since f is increasing with respect to y:
28 // If f(x, mid) >= z, the answer is in the left half (including mid)
29 if (customfunction.f(x, mid) >= z) {
30 right = mid;
31 } else {
32 // Otherwise, the answer is in the right half (excluding mid)
33 left = mid + 1;
34 }
35 }
36
37 // Check if we found an exact match where f(x, left) = z
38 if (customfunction.f(x, left) == z) {
39 // Add the valid pair [x, y] to the result list
40 result.add(Arrays.asList(x, left));
41 }
42 }
43
44 return result;
45 }
46}
471/*
2 * // This is the custom function interface.
3 * // You should not implement it, or speculate about its implementation
4 * class CustomFunction {
5 * public:
6 * // Returns f(x, y) for any given positive integers x and y.
7 * // Note that f(x, y) is increasing with respect to both x and y.
8 * // i.e. f(x, y) < f(x + 1, y), f(x, y) < f(x, y + 1)
9 * int f(int x, int y);
10 * };
11 */
12
13class Solution {
14public:
15 vector<vector<int>> findSolution(CustomFunction& customfunction, int z) {
16 vector<vector<int>> result;
17
18 // Iterate through all possible x values from 1 to 1000
19 for (int x = 1; x <= 1000; ++x) {
20 // Binary search for y value where f(x, y) == z
21 // Since f is monotonically increasing with respect to y
22 int left = 1;
23 int right = 1000;
24
25 // Binary search to find the smallest y where f(x, y) >= z
26 while (left < right) {
27 int mid = (left + right) >> 1; // Equivalent to (left + right) / 2
28
29 if (customfunction.f(x, mid) >= z) {
30 // If f(x, mid) >= z, the answer might be at mid or smaller
31 right = mid;
32 } else {
33 // If f(x, mid) < z, we need to search in the right half
34 left = mid + 1;
35 }
36 }
37
38 // Check if we found an exact match where f(x, y) == z
39 if (customfunction.f(x, left) == z) {
40 result.push_back({x, left});
41 }
42 }
43
44 return result;
45 }
46};
471/**
2 * // This is the CustomFunction's API interface.
3 * // You should not implement it, or speculate about its implementation
4 * class CustomFunction {
5 * f(x: number, y: number): number {}
6 * }
7 */
8
9/**
10 * Finds all pairs [x, y] where customfunction.f(x, y) equals z
11 * The function f is guaranteed to be monotonically increasing
12 *
13 * @param customfunction - The custom function object with method f(x, y)
14 * @param z - The target value to find
15 * @returns Array of [x, y] pairs where f(x, y) = z
16 */
17function findSolution(customfunction: CustomFunction, z: number): number[][] {
18 // Array to store all valid [x, y] pairs
19 const results: number[][] = [];
20
21 // Iterate through all possible x values from 1 to 1000
22 for (let x = 1; x <= 1000; ++x) {
23 // Binary search for y value where f(x, y) = z
24 let left = 1;
25 let right = 1000;
26
27 // Binary search to find the smallest y where f(x, y) >= z
28 while (left < right) {
29 // Calculate middle point using bit shift for efficiency
30 const mid = (left + right) >> 1;
31
32 // If f(x, mid) >= z, the answer is in the left half (including mid)
33 if (customfunction.f(x, mid) >= z) {
34 right = mid;
35 } else {
36 // Otherwise, the answer is in the right half (excluding mid)
37 left = mid + 1;
38 }
39 }
40
41 // Check if we found an exact match where f(x, left) = z
42 if (customfunction.f(x, left) === z) {
43 results.push([x, left]);
44 }
45 }
46
47 return results;
48}
49Time and Space Complexity
Time Complexity: O(n log n), where n is the value of z.
The outer loop iterates from x = 1 to x = z, which gives us O(n) iterations. For each value of x, we perform a binary search using bisect_left on the range [1, z] to find the appropriate value of y. The binary search operation takes O(log n) time since we're searching through a range of size z. The key function lambda y: customfunction.f(x, y) is called O(log n) times during each binary search. Since we perform this binary search for each of the n values of x, the total time complexity is O(n) × O(log n) = O(n log n).
Space Complexity: O(1) (excluding the output array).
The algorithm uses only a constant amount of extra space for variables x and y. The bisect_left function operates on a range object and uses O(1) additional space for its internal operations. The ans list stores the output, but this is typically not counted in space complexity analysis as it's required for the return value. Therefore, the auxiliary space complexity is O(1).
Learn more about how to find time and space complexity quickly.
Common Pitfalls
1. Inefficient Search Range for y
Pitfall: The code searches for y in the range [1, z] for every x value, but this can be optimized. Due to the monotonic property, once we find a valid pair [x₁, y₁], for the next iteration with x₂ = x₁ + 1, we know that if a valid y₂ exists, it must satisfy y₂ < y₁ (since f(x₂, y₁) > f(x₁, y₁) = z).
Solution: Use a two-pointer approach that leverages both monotonic properties simultaneously:
def findSolution(self, customfunction: 'CustomFunction', z: int) -> List[List[int]]:
result = []
x, y = 1, z
while x <= z and y >= 1:
current = customfunction.f(x, y)
if current == z:
result.append([x, y])
x += 1
y -= 1
elif current < z:
x += 1
else:
y -= 1
return result
This reduces time complexity from O(z log z) to O(z).
2. Early Termination Opportunity Missed
Pitfall: The current solution continues searching even when it's impossible to find more solutions. For example, if f(x, 1) > z, then for all y ≥ 1, f(x, y) > z, so we can stop searching entirely.
Solution: Add an early termination check:
for x in range(1, z + 1):
# Early termination: if f(x, 1) > z, no valid y exists for this or larger x
if customfunction.f(x, 1) > z:
break
# Binary search for y...
3. Unnecessary Function Calls in Binary Search
Pitfall: The shown implementation using bisect_left with a lambda function can result in redundant function calls. After bisect_left returns, we call f(x, y) again to check if it equals z.
Solution: Use a manual binary search that stores the function result:
left, right = 1, z while left <= right: mid = (left + right) // 2 current_value = customfunction.f(x, mid) if current_value == z: result.append([x, mid]) break elif current_value < z: left = mid + 1 else: right = mid - 1
This ensures each f(x, y) value is computed only once during the search.
Which of the following shows the order of node visit in a Breadth-first Search?

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!