Use two queues: q1, q2
.
Start with q1,q2
empty.
(In the following, define q.head() == 1
if q
is empty, it is needed only for first iterations)
Repeat while `min{q1.head(), q2.head()} <n`:
let x = min{q1.head(), q2.head()}
yield x
remove x from relevant queue
q1.add(x*2)
q2.add(x*5)
The idea is, if x1
was processed before x2
, then it means x1<x2
, and thus x1*2 < x2*2
and x1*5 < x2*5
- so the queues are maintained order, and all you have to do at each point is check which of the queues should be polled at each step, which is fairly simple.
Note that you can easily trim duplicates as well this way, because the numbers are produced in order, and you just need to skip numbers if it is identical to the last number that was processed.
Pros of this solution:
- Complexity of this solution is linear in the number of elements
produced.
- Produced list is already sorted, if you need it to be.
- If you need
k
first elements, this solution is pretty efficient, as it runs in O(k)
, and you just break after producing the k
th element.