Given a function fn, return a curried version of that function.
A curried function is a function that accepts fewer or an equal number of parameters as the original function and returns either another curried function or the same value the original function would have returned.
In practical terms, if you called the original function like sum(1,2,3), you would call the curried version like csum(1)(2)(3), csum(1)(2,3), csum(1,2)(3), or csum(1,2,3). All these methods of calling the curried function should return the same value as the original.
Example 1:
Input:
fn = function sum(a, b, c) { return a + b + c; }
inputs = [[1],[2],[3]]
Output: 6
Explanation:
The code being executed is:
const curriedSum = curry(fn);
curriedSum(1)(2)(3) === 6;
curriedSum(1)(2)(3) should return the same value as sum(1, 2, 3).
Example 2:
Input:
fn = function sum(a, b, c) { return a + b + c; }
inputs = [[1,2],[3]]
Output: 6
Explanation:
curriedSum(1, 2)(3) should return the same value as sum(1, 2, 3).
Example 3:
Input:
fn = function sum(a, b, c) { return a + b + c; }
inputs = [[],[],[1,2,3]]
Output: 6
Explanation:
You should be able to pass the parameters in any way, including all at once or none at all.
curriedSum()()(1, 2, 3) should return the same value as sum(1, 2, 3).
Example 4:
Input:
fn = function life() { return 42; }
inputs = [[]]
Output: 42
Explanation:
currying a function that accepts zero parameters should effectively do nothing.
curriedLife() === 42
Constraints:
1 <= inputs.length <= 10000 <= inputs[i][j] <= 1050 <= fn.length <= 1000inputs.flat().length == fn.lengthfn.length > 0 then the last array in inputs is not emptyfn.length === 0 then inputs.length === 1 Problem Overview: The task asks you to convert a normal function into a curried version. Instead of passing all arguments at once, the returned function should accept arguments across multiple calls and only execute the original function when enough parameters have been collected.
Approach 1: Recursive Argument Collector (O(n) time, O(n) space)
The common solution uses a closure that keeps track of the arguments passed so far. Each call gathers new parameters and checks whether the total number of collected arguments is at least the original function's arity (fn.length). If enough arguments exist, execute fn(...args). Otherwise return another function that continues collecting arguments. Recursion naturally models the repeated chaining behavior (curried(a)(b)(c)). Time complexity is O(n) where n is the number of arguments eventually supplied, since each argument is processed once. Space complexity is O(n) due to stored arguments and closure scope.
This technique relies heavily on JavaScript closures and functional programming behavior. The closure preserves previously provided arguments between calls, which allows partial application without global state. If you are reviewing functional design patterns, this pattern closely relates to functional programming and recursion concepts.
Approach 2: Iterative Closure with Argument Buffer (O(n) time, O(n) space)
Another implementation keeps an argument buffer inside a closure rather than passing arguments recursively. Every time the returned function is called, append new parameters into an array. After appending, check whether the buffer length reaches fn.length. Once the required count is met, call the original function using the buffered arguments. The logic is iterative but still depends on closures to maintain state across invocations. Time complexity remains O(n) since each argument is appended once, and space complexity is also O(n) for storing the collected parameters.
Approach 3: Using Function.bind for Partial Application (O(n) time, O(n) space)
JavaScript's Function.bind can partially apply arguments to a function. You can repeatedly bind arguments until the total count satisfies the required arity. Each bind returns a new function with pre-filled parameters. When enough arguments accumulate, invoke the original function. Although elegant, this method creates multiple bound function instances, which can introduce additional overhead. Complexity still remains O(n) time and O(n) space due to argument accumulation.
Recommended for interviews: The recursive closure approach is the most expected answer. It directly demonstrates understanding of closures, argument spreading, and functional composition. Showing a simple brute-style argument collector proves you understand the problem, while the recursive curry implementation highlights deeper JavaScript knowledge and clean functional design.
TypeScript
| Approach | Time | Space | When to Use |
|---|---|---|---|
| Recursive Argument Collector | O(n) | O(n) | Most common interview solution; clean implementation using closures and recursion |
| Iterative Closure with Argument Buffer | O(n) | O(n) | Useful when you prefer explicit state management rather than recursion |
| Function.bind Partial Application | O(n) | O(n) | Demonstrates JavaScript built-in partial application, but less common in interviews |
Curry - Leetcode 2632 - JavaScript 30-Day Challenge • NeetCodeIO • 12,756 views views
Watch 4 more video solutions →Practice Curry with our built-in code editor and test cases.
Practice on FleetCodePractice this problem
Open in Editor