Maximum Currency Conversion with Arbitrage
Reported by candidates from Google's online assessment. Pattern, common pitfall, and the honest play if you blank under the timer.
Google's October 2025 OA includes a currency conversion problem where USD to CAD to JPY at 1.3 then 100.0 beats the GBP route, and the twist is that a bad cycle can make the answer unbounded. It's a directed graph with multiplicative weights, so think Bellman-Ford with a positive-cycle check, not plain shortest path. You return -1.0 for unreachable, -2.0 for a gain cycle that touches the route, and the max amount otherwise. If you freeze on the cycle detection, StealthCoder is the invisible backup that reads the problem on screen and hands you a working solution during the live OA.
The problem
Each directed conversion edge i means that one unit of sources[i] converts to rates[i] units of targets[i]. Edges are directed; no reverse conversion exists unless it is listed. Starting with amount units of source, return the maximum amount of target obtainable by applying edges any number of times. Return -1.0 when target is unreachable from source. Return -2.0 when a multiplicative-gain cycle is reachable from source and can still reach target, so the obtainable amount is unbounded. Otherwise return the finite maximum amount. Using zero edges is allowed, so converting a currency to itself returns amount unless an applicable gain cycle makes it unbounded. Function maximumConversion(sources: String[], targets: String[], rates: double[], source: String, target: String, amount: double) → double Examples Example 1 sources = ["USD","CAD","USD","GBP"] targets = ["CAD","JPY","GBP","JPY"] rates = [1.3,100.0,0.8,150.0] source = "USD" target = "JPY" amount = 10.0 return = 1300.0 The USD-CAD-JPY route multiplies by 130, producing 1300. The USD-GBP-JPY route multiplies by 120. Example 2 sources = ["A","B","B"] targets = ["B","A","C"] rates = [2.0,0.6,1.0] source = "A" target = "C" amount = 1.0 return = -2.0 The cycle A-B-A multiplies the amount by 1.2. It is reachable from A and can exit through B-C, so the target amount is unbounded. Example 3 sources = ["A"] targets = ["B"] rates = [2.0] source = "B" target = "A" amount = 5.0 return = -1.0 The only edge points from A to B, so A is unreachable from B. Constraints 0 <= sources.length == targets.length == rates.length <= 5000 There are at most 300 distinct currency codes across the edges and query. Each currency code contains 1 to 10 uppercase English letters. 0 < rates[i] <= 1000000 and 0 < amount <= 1000000000. Any directed cycle's product is either at most 1 or differs from 1 by at least 10^-9. Every finite answer is representable by a double.
Reported by candidates. Source: FastPrep
Pattern and pitfall
The trick is turning products into sums. Take log of each rate and you're maximizing a path sum, which means a positive cycle is your arbitrage. Run Bellman-Ford style relaxation for maximum, over at most 300 nodes and 5000 edges. After n-1 rounds, any edge that still relaxes marks a node on or downstream of a gain cycle. Then the pitfall: that node only matters if it's reachable from source AND can reach target. So compute forward reachability from source and backward reachability to target, and only count cycles inside that intersection. Check reachability first and return -1.0 before anything else. Don't use logs for the final value, track raw products, and use an epsilon for relaxation. The constraint that cycles differ from 1 by 1e-9 is your epsilon hint. If the source equals the target, you still need the cycle check before returning amount. StealthCoder is the hedge if the reachability intersection slips your mind mid-assessment.
The honest play: practice the pattern, and have StealthCoder ready for the one you didn't see coming.
You can drill Maximum Currency Conversion with Arbitrage cold, or you can hedge it. StealthCoder runs invisibly during screen share and surfaces a working solution in under 2 seconds. The proctor sees the IDE. They don't see what's behind it. Built for the candidate who saw this exact problem leak two days before his OA and wondered if anyone had a play.
Get StealthCoderRelated leaked OAs
You've seen the question.
Make sure you actually pass Google's OA.
Google reuses patterns across OAs. Built for the candidate who saw this exact problem leak two days before his OA and wondered if anyone had a play. Works on HackerRank, CodeSignal, CoderPad, and Karat.
Maximum Currency Conversion with Arbitrage FAQ
What's the core trick in this Google currency conversion problem?+
Treat it as a longest path problem with multiplicative weights. Bellman-Ford with max-product relaxation works, and a relaxation that still succeeds after n-1 rounds signals a gain cycle. Then check whether that cycle is reachable from source and can reach target.
Why return -2.0 instead of just the big number?+
A gain cycle on the route lets you loop forever and multiply the amount without limit. So the answer is unbounded. But only cycles that sit between source and target count. A cycle elsewhere in the graph is irrelevant and shouldn't change your answer.
What happens when source equals target?+
You return amount, since using zero edges is allowed. The exception is when a gain cycle is reachable from source and can still reach target, which here means it loops back through source. Then you return -2.0. Run the cycle check before the shortcut.
Can I use Floyd-Warshall instead of Bellman-Ford?+
Yes. With at most 300 currencies, Floyd-Warshall with max-product is fine. A node whose self-conversion exceeds 1 is on a gain cycle. Then test that the node is reachable from source and reaches target. Bellman-Ford is usually less code for a single query.
How do I prep for this in 48 hours?+
Write Bellman-Ford with negative cycle detection once, then flip it to max-product. Practice marking nodes affected by cycles using forward and backward BFS. Map currency strings to integer IDs first. Test your code on the three given examples, including the unreachable one.