Given an integer n, return a counter function. This counter function initially returns n and then returns 1 more than the previous value every subsequent time it is called (n, n + 1, n + 2, etc).
Example 1:
Input: n = 10 ["call","call","call"] Output: [10,11,12] Explanation: counter() = 10 // The first time counter() is called, it returns n. counter() = 11 // Returns 1 more than the previous time. counter() = 12 // Returns 1 more than the previous time.
Example 2:
Input: n = -2 ["call","call","call","call","call"] Output: [-2,-1,0,1,2] Explanation: counter() initially returns -2. Then increases after each sebsequent call.
Constraints:
-1000 <= n <= 10000 <= calls.length <= 1000calls[i] === "call"Problem Overview: You start with an integer n. Build a function that returns n on the first call, n + 1 on the second call, and continues increasing by one each time. The key requirement is that the returned function must remember the updated value between calls.
Approach 1: Closure-based Approach (O(1) time, O(1) space)
This approach relies on a closure, where an inner function captures variables from its outer scope. Define a function like createCounter(n) and return another function counter(). The inner function accesses the outer variable n, returns its current value, then increments it. Because the closure keeps a reference to n, the value persists across calls without needing global state. Each call performs a constant-time read and increment operation, so time complexity is O(1), and only one integer is stored, giving O(1) space.
This pattern is common when working with closures and functional programming concepts. It’s concise and maps directly to how languages like JavaScript and Python manage function scope.
Approach 2: Class-based Approach (O(1) time, O(1) space)
A class can also maintain the counter state. Create a class with a field such as count initialized to n. The method that acts as the counter returns the current value and then increments the field. Each invocation simply reads and updates the instance variable. The work per call remains constant, giving O(1) time complexity, and the object stores only one integer, so space complexity is O(1).
This approach mirrors traditional object-oriented design. Instead of capturing variables through a closure, the state is stored explicitly in the object. It can feel more natural in languages where classes are the primary abstraction, such as Java, C++, or C#.
Recommended for interviews: The closure-based solution is usually the expected answer because the problem specifically tests whether you understand how functions can retain state after returning. Showing the class-based version demonstrates that you recognize the underlying concept: persistent state across calls. The closure approach is shorter and idiomatic in languages that support first-class functions, while the class approach highlights the same logic using object-oriented structure.
In this approach, we use a closure to maintain the state across multiple calls to the counter function. The closure lets us keep track of the last counted value between function calls.
This Python solution utilizes closures, where the counter function maintains its state using the nonlocal keyword to access and modify the variable n, which isn't local to the function itself. The inner counter function increments this value each time it is called and returns the current count.
Time Complexity: O(1) per call.
Space Complexity: O(1) for maintaining the state.
This approach uses object-oriented programming to keep track of the counter's state across multiple invocations by encapsulating the state within a class instance.
This Python solution utilizes a class where the count is maintained as an instance variable. Calling the instance returns the current count, increments it, and stores the new state.
Time Complexity: O(1) per call.
Space Complexity: O(1) for the instance state.
TypeScript
| Approach | Complexity |
|---|---|
| Closure-based Approach | Time Complexity: O(1) per call. |
| Class-based Approach | Time Complexity: O(1) per call. |
| Default Approach | — |
| Approach | Time | Space | When to Use |
|---|---|---|---|
| Closure-based Approach | O(1) per call | O(1) | Best when the language supports closures and you want concise stateful behavior |
| Class-based Approach | O(1) per call | O(1) | Useful in object-oriented languages or when state should be encapsulated in an object |
Counter (Closure - Day2) - Leetcode 2620 - JavaScript 30-Day Challenge • NeetCodeIO • 40,400 views views
Watch 9 more video solutions →Practice Counter with our built-in code editor and test cases.
Practice on FleetCodePractice this problem
Open in Editor