Determine reachability and optimize task scheduling
Company: Amazon
Role: Software Engineer
Category: Coding & Algorithms
Difficulty: Medium
Interview Round: Take-home Project
Quick Answer: This question evaluates understanding of discrete reachability and resource-constrained scheduling, testing the ability to reason about iterative coordinate transformations and to optimize parallel task assignment under type and memory limits.
Reaching Points
Constraints
- 1 <= a, b, c, d <= 10^9
- Each operation strictly increases one coordinate, so coordinates never decrease.
- Work backwards from (c, d) using the modulo operation to collapse the otherwise-exponential forward search.
Examples
Input: (1, 1, 3, 5)
Expected Output: True
Explanation: (1,1)->(1,2)->(3,2)->(3,5).
Input: (1, 1, 2, 2)
Expected Output: False
Explanation: From (1,1) any move yields a point with two distinct coordinates that stay coprime; (2,2) is unreachable.
Input: (1, 1, 1, 1)
Expected Output: True
Explanation: Start already equals target; zero operations needed.
Input: (3, 3, 12, 9)
Expected Output: True
Explanation: Reverse: (12,9)->(3,9)->(3,6)->(3,3).
Input: (1, 2, 1000000000, 1)
Expected Output: False
Explanation: d would have to shrink below its start value b=2, which the operations can never do.
Input: (2, 4, 6, 4)
Expected Output: True
Explanation: (2,4)->(6,4) via (x,y)->(x+y,y).
Input: (1, 1, 1, 1000000)
Expected Output: True
Explanation: Keep applying (x,y)->(x,x+y) with x fixed at 1 to grow the second coordinate to 1000000.
Input: (5, 7, 5, 7)
Expected Output: True
Explanation: Start equals target.
Hints
- A forward BFS/DFS explodes exponentially. Reverse the process: the predecessor of (c, d) is either (c - d, d) (if c > d) or (c, d - c) (if d > c).
- Repeatedly subtracting the smaller coordinate from the larger is exactly the Euclidean algorithm, so replace the loop of subtractions with a single modulo (%) operation.
- When one coordinate finally matches its target (e.g. c == a), the other must be reachable by adding the fixed coordinate a whole number of times: check that (d - b) is a non-negative multiple of a.
Minimum Time to Process Same-Type Tasks
Constraints
- Tasks of different types can never share a time unit.
- 1 <= taskMemory[i], taskType[i]; 1 <= maxMemory.
- Group by type, then solve each group independently and sum the results.
Examples
Input: ([4, 6, 5, 5], [1, 1, 2, 2], 10)
Expected Output: 2
Explanation: Type 1: 4+6=10 pairs. Type 2: 5+5=10 pairs. Two time units.
Input: ([7, 8, 3, 2], [1, 1, 1, 1], 10)
Expected Output: 2
Explanation: Sorted [2,3,7,8]: pair 2+8=10 and 3+7=10. Two units.
Input: ([6, 6, 6], [1, 1, 1], 10)
Expected Output: 3
Explanation: 6+6=12 > 10 so nothing pairs; three units.
Input: ([1], [5], 10)
Expected Output: 1
Explanation: Single task runs alone in one unit.
Input: ([5, 5, 5, 5], [1, 2, 1, 2], 10)
Expected Output: 2
Explanation: Two type-1 tasks pair (one unit); two type-2 tasks pair (one unit).
Input: ([9, 9, 9, 9], [1, 1, 1, 1], 10)
Expected Output: 4
Explanation: Every pair sums to 18 > 10, so all four run alone.
Input: ([], [], 10)
Expected Output: 0
Explanation: No tasks, no time.
Input: ([3, 3, 3, 3, 3, 3], [1, 1, 1, 2, 2, 2], 6)
Expected Output: 4
Explanation: Each type has three 3's: pair two (3+3=6) and one alone = 2 units per type, 4 total.
Hints
- Tasks of different types can never be paired, so split the tasks into independent groups by type and solve each group on its own.
- Within one type, sort the memory values. Use two pointers: try to pair the smallest remaining task with the largest remaining task.
- If the smallest and largest fit together (sum <= maxMemory), pair them (one time unit, advance both pointers); otherwise the largest must run alone (one time unit, move only the right pointer).