Katkat

Courier Drone: Fastest Fixed-Distance Segment From Tick Logs

OptiverSoftware Engineer · Online Assessment

Last updated

From per-tick distance logs, find the highest average speed over any time span that covers exactly a target distance, where spans may start and end partway through a tick. Tests prefix sums, linear interpolation, and showing that an optimal span touches a tick boundary.

A delivery drone reports its progress in fixed ticks. ticks[i] is the number of meters it flew during tick i. Every tick lasts tick_seconds seconds, so tick i covers the time range [i * tick_seconds, (i + 1) * tick_seconds].

Inside a tick the drone flies at a constant speed. After t seconds of tick i it has covered ticks[i] * t / tick_seconds meters of that tick.

The operations team wants the drone's best target-meter segment: the highest average speed over any continuous time span [a, b] in which the drone covers exactly target meters. That average is target / (b - a).

def best_segment_speed(ticks: list[int], tick_seconds: float, target: int) -> float: ...

Rules:

  • a and b can be any real times with 0 <= a < b <= len(ticks) * tick_seconds. A span can start or end partway through a tick.
  • Ticks with 0 meters (hovering) still count toward the elapsed time of any span that contains them.
  • A span can sit entirely inside one tick if that tick alone covers at least target meters.
  • Answers within 1e-6 relative error are accepted.

Examples

ticks = [100, 100, 100, 100, 100], tick_seconds = 10, target = 500
answer = 10.0

The drone holds a steady 10 m/s, so every 500 m span takes 50 s.

ticks = [50, 300, 0, 250, 150], tick_seconds = 10, target = 500
answer = 17.857142857...   (= 500 / 28)

Start at t = 10 (the start of the 300 m tick). Then fly 300 m, hover for 10 s, and fly 200 of the next 250 m in 8 s. That is 28 s in total. No other span is shorter.

ticks = [20, 900, 40], tick_seconds = 10, target = 500
answer = 90.0

The middle tick alone moves at 90 m/s, so 500 m fit inside it.

Constraints

  • 1 <= len(ticks) <= 10^5, 0 <= ticks[i] <= 10^5
  • 1 <= target, sum(ticks) >= target
  • Running totals can exceed 2^31. Use 64-bit integers in fixed-width languages.
  • Aim for O(n log n) or O(n).

Hints

Hint 1

Build prefix sums P so that P[i] is the distance covered by the start of tick i. Cumulative distance D(t) is then a piecewise-linear, non-decreasing function of time.

Hint 2

Fix the start a. The end b is the earliest time with D(b) = D(a) + target, and you can find it with a binary search over P plus one interpolation.

Hint 3

Think about the span length b(a) - a as a function of a. Between the points where a or b crosses a tick boundary, it is linear. Where must a minimum of a piecewise-linear function lie?

Hint 4

So you only need two families of candidates: spans that start on a tick boundary and spans that end on one.

Follow-up questions

  • Make it O(n) with two pointers. What invariant makes the pointer monotone?
  • Ops also wants the slowest target-meter segment. Does the boundary argument still hold?
  • What if speed inside a tick changed linearly instead of staying constant?
  • How would you answer many different targets on the same log efficiently?