Watch 10 video solutions for Counter II, a easy level problem. This walkthrough by NeetCodeIO has 27,525 views views. Want to try solving it yourself? Practice on FleetCode or read the detailed text solution.
Write a function createCounter. It should accept an initial integer init. It should return an object with three functions.
The three functions are:
increment() increases the current value by 1 and then returns it.decrement() reduces the current value by 1 and then returns it.reset() sets the current value to init and then returns it.
Example 1:
Input: init = 5, calls = ["increment","reset","decrement"] Output: [6,5,4] Explanation: const counter = createCounter(5); counter.increment(); // 6 counter.reset(); // 5 counter.decrement(); // 4
Example 2:
Input: init = 0, calls = ["increment","increment","decrement","reset","reset"] Output: [1,2,1,0,0] Explanation: const counter = createCounter(0); counter.increment(); // 1 counter.increment(); // 2 counter.decrement(); // 1 counter.reset(); // 0 counter.reset(); // 0
Constraints:
-1000 <= init <= 10000 <= calls.length <= 1000calls[i] is one of "increment", "decrement" and "reset"Problem Overview: You need to design a counter that starts from an initial value and supports three operations: increment(), decrement(), and reset(). Each method updates or restores the internal state and returns the current counter value.
Approach 1: Closure-Based Counter (O(1) time, O(1) space)
This approach relies on closures to store the counter state inside a function scope. The outer function initializes the counter value, while the returned object exposes methods that operate on that captured variable. Each call to increment() increases the stored value, decrement() reduces it, and reset() restores it to the original initialization value. Because the variable lives in the closure, it persists across calls without using global state.
The key insight is that closures allow functions to retain access to variables from their creation scope. That makes them perfect for lightweight stateful utilities like counters. Each operation performs a constant‑time arithmetic update, so every method runs in O(1) time with O(1) additional space. This approach is common in JavaScript and Python implementations and is frequently discussed when learning closures and functional design patterns.
Approach 2: Class-Based Counter Object (O(1) time, O(1) space)
An alternative design uses an explicit class with instance variables to store the counter state. The constructor receives the initial value and stores both the current counter and the original value for resets. Methods like increment(), decrement(), and reset() modify the instance variable and return the updated value.
This approach follows classic object-oriented programming principles. State lives in class fields instead of closures, and behavior is defined through instance methods. The logic remains straightforward: update the stored integer and return the result. Each operation still runs in constant time O(1) with O(1) space overhead.
Class-based design is often preferred in strongly typed languages like Java or C#, where objects and method definitions are the natural way to encapsulate state. It also scales better if the counter later gains additional behaviors or configuration.
Recommended for interviews: The closure-based implementation is usually the expected solution in JavaScript because it demonstrates understanding of function scope and persistent state. The class-based approach is equally valid and shows good design thinking in languages centered around objects. Showing both approaches demonstrates strong grasp of state management and abstraction.
| Approach | Time | Space | When to Use |
|---|---|---|---|
| Closure-Based Counter | O(1) per operation | O(1) | Best for JavaScript or Python when demonstrating closures and functional state management |
| Class-Based Counter Object | O(1) per operation | O(1) | Preferred in Java or C# where object-oriented structure is standard |