Solve swaps, graph paths, and movie DP
Company: Akuna Capital
Role: Software Engineer
Category: Coding & Algorithms
Difficulty: Medium
Interview Round: Take-home Project
Quick Answer: This interview question evaluates algorithm design, data structures, correctness, complexity, edge cases, and implementation details in a realistic interview setting. A strong answer for Solve swaps, graph paths, and movie DP states assumptions, handles edge cases, explains trade-offs, and shows how to validate the result clearly.
Minimum Swaps to Sort Descending
Constraints
- 0 <= n <= 10^5
- All values in A are distinct
- Values fit in a 64-bit signed integer
- If duplicates were allowed, ties must be broken by a stable rule (e.g. original index) before building the target permutation.
Examples
Input: ([4, 3, 1, 2],)
Expected Output: 1
Explanation: Target is [4,3,2,1]; only 1 and 2 are swapped (one 2-cycle) -> 1 swap.
Input: ([1, 2, 3, 4, 5],)
Expected Output: 2
Explanation: Reversing 1..5 forms two 2-cycles (1<->5, 2<->4); the middle is fixed -> 2 swaps.
Input: ([5, 4, 3, 2, 1],)
Expected Output: 0
Explanation: Already strictly descending -> 0 swaps.
Input: ([],)
Expected Output: 0
Explanation: Empty array needs no swaps.
Input: ([7],)
Expected Output: 0
Explanation: Single element is trivially sorted.
Input: ([2, 1],)
Expected Output: 0
Explanation: [2,1] is already descending.
Input: ([1, 2],)
Expected Output: 1
Explanation: Swap the two elements to get [2,1].
Input: ([-3, -1, -2, 0, 5],)
Expected Output: 3
Explanation: Descending target [5,0,-1,-2,-3]; permutation splits into a 2-cycle and a 3-cycle -> 1 + 2 = 3 swaps.
Input: ([10, 30, 20, 40],)
Expected Output: 1
Explanation: Target [40,30,20,10]; 10 and 40 form one 2-cycle, 30 and 20 are already placed -> 1 swap.
Hints
- Sorting descending tells you where every element must end up; the problem reduces to sorting a permutation by swaps.
- Minimum swaps to fix a permutation = (number of elements out of place) - (number of cycles among them). Equivalently each cycle of length k costs k-1 swaps.
- Walk each unvisited index, follow the chain i -> target_position(A[i]) until you return to the start, and add (cycle_length - 1).
Count Simple Paths in an Undirected Graph
Constraints
- 1 <= n <= 20 (enumeration is exponential; small graphs only)
- 0 <= u, v < n, edges are undirected and may be assumed simple (no self-loops / parallel edges)
- 0 <= s, t < n
- When s == t the count includes the trivial zero-length path (1).
Examples
Input: (4, [[0, 1], [0, 2], [1, 3], [2, 3]], 0, 3)
Expected Output: 2
Explanation: The two routes 0-1-3 and 0-2-3 are the only simple paths.
Input: (2, [[0, 1]], 0, 1)
Expected Output: 1
Explanation: A single edge gives exactly one path.
Input: (3, [[0, 1], [1, 2]], 0, 2)
Expected Output: 1
Explanation: Only the chain 0-1-2 connects 0 to 2.
Input: (3, [], 0, 2)
Expected Output: 0
Explanation: No edges means s and t are disconnected.
Input: (1, [], 0, 0)
Expected Output: 1
Explanation: s == t: the trivial empty path counts as one.
Input: (4, [[0, 1], [1, 2], [2, 3], [0, 3], [0, 2]], 0, 3)
Expected Output: 3
Explanation: Paths: 0-3, 0-2-3, and 0-1-2-3.
Input: (5, [[0, 1], [0, 2], [1, 2], [2, 3], [3, 4], [1, 4]], 0, 4)
Expected Output: 4
Explanation: Paths: 0-1-4, 0-1-2-3-4, 0-2-1-4, 0-2-3-4.
Input: (3, [[0, 1]], 0, 2)
Expected Output: 0
Explanation: Vertex 2 is isolated, so there is no path from 0 to 2.
Hints
- Build an adjacency list first; then DFS from s, recursing only into neighbors not on the current path.
- Use a boolean visited array: set it true before recursing into a neighbor and reset it to false afterward (classic backtracking).
- Increment the counter exactly when the current vertex equals t, then return without exploring further from t.
Movie Ratings Scheduling (Weighted Interval Scheduling)
Constraints
- 0 <= m <= 10^5
- Each movie is [start, end, rating] with end > start
- rating >= 0
- Movies sharing an endpoint (one ends exactly when another starts) are NOT considered overlapping.
Examples
Input: ([[1, 3, 5], [2, 5, 6], [4, 6, 5], [6, 7, 4]],)
Expected Output: 14
Explanation: Pick [1,3,5] + [4,6,5] + [6,7,4] = 14; they are pairwise non-overlapping.
Input: ([],)
Expected Output: 0
Explanation: No movies -> total rating 0.
Input: ([[0, 10, 100]],)
Expected Output: 100
Explanation: A single movie is always chosen.
Input: ([[1, 2, 10], [2, 3, 10], [3, 4, 10]],)
Expected Output: 30
Explanation: All three touch only at endpoints, so all can be taken -> 30.
Input: ([[1, 4, 50], [2, 3, 10], [3, 5, 10]],)
Expected Output: 50
Explanation: The single high-rated [1,4,50] beats any combination of the smaller overlapping movies.
Input: ([[1, 3, 20], [3, 5, 20], [1, 5, 30]],)
Expected Output: 40
Explanation: [1,3,20] + [3,5,20] = 40 beats the single [1,5,30].
Input: ([[1, 100, 1], [1, 2, 5], [2, 3, 5], [3, 4, 5]],)
Expected Output: 15
Explanation: Three short non-overlapping movies (5+5+5) beat the long low-rated one.
Input: ([[5, 6, 3], [1, 2, 3], [3, 4, 3], [2, 3, 3], [4, 5, 3]],)
Expected Output: 15
Explanation: All five chain endpoint-to-endpoint with no overlap -> 5 * 3 = 15.
Hints
- Sort the movies by end time so that when you process movie i, every compatible earlier movie has already been considered.
- For each movie, binary-search the end-time array to find p(i): the last movie ending at or before this movie's start.
- DP recurrence: dp[i] = max(skip this movie = dp[i-1], take it = rating_i + dp[p(i)]). The answer is dp[m].