Problem 1237

Abstract / Summary

Find two positive integers whose product equals target a and sum equals target b if they exist.

Note

The full problem description, including helpful examples, can be found on LeetCode.

Python 1237.py

class Solution:
    def findSolution(self, customfunction: 'CustomFunction', z: int) -> List[List[int]]:
        # [ 1,2,...,1000 ]
        low  =    1
        high = 1000
        all  = list(range(low, high + 1))

        for x in all:
            # no solution for x ? (these checks aren't needed, they just improve performance)
            if customfunction.f(x, low)  > z:
                break
            if customfunction.f(x, high) < z:
                continue

            # find lowest y where f(x, y) == z
            left  = bisect_left(all, z,     key = lambda y, x=x : customfunction.f(x, y))
            # find lowest y where f(x, y) > z
            right = bisect_left(all, z + 1, key = lambda y, x=x : customfunction.f(x, y))
            # linear scan until f(x, y) becomes too large
            for y in range(all[left], all[right]):
                yield [ x, y ]
21 lines | 905 bytes | submitted November 24, 2023 | GitHub   35% comment ratio | tab size 4 | low complexity

Difficulty

This problem is ranked as
easy medium hard

and has an acceptance rate of about 70% (100k+ submissions).

Typical patterns to solve this problem:
  • Binary Search
  • Interactive
  • Math
  • Two Pointers
I solved 663 easy, 1250 medium and 309 hard problems

AI Disclaimer

Every single line of code was written by me, 100% from scratch, between August 2023 and August 2024.
However, two years later I set up this website and used various AI tools to generate most of the walkthrough / explanations below.

See this dedicated page for more details.
LeetCode profile | GitHub repo

Code Walkthrough

Overview

The provided implementation searches for all integer pairs ((x, y)) within the inclusive range ([1, 1000]) that satisfy the equation customfunction.f(x, y) == z. The method returns a generator that yields each qualifying pair as a two-element list. The algorithm combines a linear scan over the possible values of x with binary search techniques to efficiently locate the corresponding y values for each x.

Key Steps

The first step creates the complete search domain for both variables.

low  = 1
high = 1000
all  = list(range(low, high + 1))

A loop iterates over every candidate x in the domain.

for x in all:

Inside the loop two quick checks are performed to eliminate x values that cannot possibly produce a solution. The first check stops the loop entirely when the smallest possible y already yields a value larger than z.

if customfunction.f(x, low) > z:
    break

The second check skips the current x when even the largest possible y is still smaller than z.

if customfunction.f(x, high) < z:
    continue

When an x passes the preliminary filters, two binary searches determine the interval of y values that could satisfy the equation. The left bound finds the smallest y for which the function value is at least z.

left = bisect_left(all, z, key=lambda y, x=x: customfunction.f(x, y))

The right bound finds the smallest y for which the function value exceeds z.

right = bisect_left(all, z + 1, key=lambda y, x=x: customfunction.f(x, y))

With the interval [left, right) identified, a simple linear scan enumerates each y that yields exactly z.

for y in range(all[left], all[right]):
    yield [x, y]

The use of yield makes the method a generator, allowing callers to consume results lazily without allocating a full list of pairs.

Edge Cases Handled

When the function value at the minimum y already exceeds z, the outer loop terminates early because no larger x can produce a smaller result, given the monotonic nature implied by the checks. Conversely, if the function value at the maximum y is still below z, the current x is skipped because no y in the domain can satisfy the target. The binary searches gracefully handle situations where no y meets the condition: if the left and right indices are equal, the subsequent for loop iterates over an empty range, producing no output for that x. This behavior correctly represents the absence of solutions without raising errors.

Performance Optimizations

The early break condition eliminates entire suffixes of the x domain once the function value surpasses z at the lowest y. The continue condition skips entire prefixes of the y domain for a given x when the function value cannot reach z. By employing bisect_left with a custom key, the algorithm narrows the candidate y interval to the smallest possible range, reducing the number of function evaluations needed for each x. The final linear scan only processes the narrowed interval, avoiding unnecessary checks outside the feasible region. Additionally, the generator pattern prevents the accumulation of all result pairs in memory, delivering each pair on demand and keeping the runtime footprint low.

written by openai gpt

ELI5 - Simplified Explanation

Imagine there is a secret treasure box that only opens when two hidden numbers add up to a special goal number. This computer program acts like a detective trying to solve these math puzzles.

First, the detective creates a list of numbers from one to one thousand to test as possible choices. It walks through each number one by one to see if it can be the first half of the secret pair. If a number is already too big to possibly work, the detective stops searching because it knows the answer cannot be found there.

For every number that looks like a good guess, the detective uses a clever trick to search through the second set of numbers very quickly. Think of this like looking through a library of pages; instead of turning every single page to find the story, the detective jumps to the middle of the book to decide which direction to look.

Once the detective finds the right spot, it carefully checks all the numbers that match the goal. When everything clicks and the two numbers combine to equal the secret target, the detective puts that pair of numbers aside to show you that it found a match. This continues until the detective has looked at every possible combination.

written by google gemini

Code Quality

Several LLMs ranked my code quality on a scale from 1 (very poor) to 10 (outstanding):
n = 27 | median = 6 | μ = 5.67 | σ = 1.91

Complexity Analysis

not analyzed yet

Other Solutions

I wrote a basic crawler to find other solutions to that problem.
Obviously, I did that after I solved the problem myself.

In general, AlgoMonster and WalkCCC solutions are high-quality and always worth a look.
I haven't checked most of the other solutions, but they might be helpful as well.

And of course, the LeetCode forum is always a good place (or even the best) to look for alternative approaches.

(click on a column header to sort the table)
author
author solutions
www AlgoMonster C++ Python Java TS
WalkCCC C++ Python Java
leetcode.ca C++ Python Java Go TS
MemoryLimitExceeded C++ Python
Progiez C++ Python Java
github BigEggStudy C#
black-shadows C++
charles-wangkai Java
DimitrisJim C
fsq C++
JoshCrozier JS
keineahnung2345 C++
lkwq007 Python
suxrobGM C#
varunu28 Java
wisdompeak C++
YuriSpiridonov Python
AlgoMonster C++, Python, Java, TypeScript
WalkCCC C++, Python, Java
leetcode.ca C++, Go, Java, Python, TypeScript
MemoryLimitExceeded Python, C++
Progiez C++, Java, Python
BigEggStudy C#
black-shadows C++, C++
charles-wangkai Java
DimitrisJim C
fsq C++
JoshCrozier JavaScript
keineahnung2345 C++
lkwq007 Python
suxrobGM C#
varunu28 Java
wisdompeak C++
YuriSpiridonov Python
29 links | 17 authors | 8 languages

Videos

2 videos   did my crawler come up with invalid videos ? drop me a line.

Solved On The Same Day

10 solutions   November 24, 2023

Extra

There are a few extra pages giving you some insights into my setup:
  • Tech Stack - my development environment and tools
  • AI - how AI helped me create this website (NOT solving the problems)
  • Progress - progression over time
  • Quality - code quality