Skip to main content

Counter II - Solution & Explanation

Easy6 min readAsked at: Amazon, Google, Yandex
Practice this problem

Problem Statement

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 <= 1000
  • 0 <= calls.length <= 1000
  • calls[i] is one of "increment", "decrement" and "reset"

Approach Overview

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 1: Closure-Based Counter

This approach uses closure to maintain the state of the counter. We create an outer function that returns three inner functions: increment, decrement, and reset. These functions have access to the outer function's scope where the initial state and current state are maintained.

The createCounter function accepts an initial value and returns an object containing three methods. The current variable is enclosed within the returned object, allowing each of the methods to manipulate the state properly. The increment method increases the counter, the decrement method decreases it, and the reset method restores it to its initial value.

Code

JavaScript

Python

Complexity

Time Complexity: O(1) for each operation since they perform a constant amount of work.
Space Complexity: O(1), only a few variables are used to hold the state.

Try this approach in the editor →

Approach 2: Class-Based Counter Object

This approach involves creating a class outside the function that models the counter with methods for incrementing, decrementing, and resetting. An instance of this class is created and returned by the createCounter function.

A Java class named Counter is defined with private fields to hold the current and initial values. Its methods implement the required functionalities. The CounterFactory class provides a static method to create a counter instance.

Code

Java

C#

Complexity

Time Complexity: O(1) per operation.
Space Complexity: O(1) as the counter uses a fixed amount of memory.

Try this approach in the editor →

Approach 3: Default Approach

Code

TypeScript

Try this approach in the editor →

Complexity Comparison

ApproachComplexity
Closure-Based Counter

Time Complexity: O(1) for each operation since they perform a constant amount of work.
Space Complexity: O(1), only a few variables are used to hold the state.

Class-Based Counter Object

Time Complexity: O(1) per operation.
Space Complexity: O(1) as the counter uses a fixed amount of memory.

Default Approach—

Detailed Complexity Analysis

ApproachTimeSpaceWhen to Use
Closure-Based CounterO(1) per operationO(1)Best for JavaScript or Python when demonstrating closures and functional state management
Class-Based Counter ObjectO(1) per operationO(1)Preferred in Java or C# where object-oriented structure is standard

Video Solution

Counter (Closure - Day3) - Leetcode 2665 - JavaScript 30-Day Challenge • NeetCodeIO • 28,025 views views

Watch 9 more video solutions →

Frequently Asked Questions

Is Counter II easy or hard?
Counter II is categorized as an Easy problem. The challenge focuses on designing a small API and correctly maintaining internal state rather than complex algorithms or data structures.
Counter II Python/Java solution
Python solutions typically use closures where an outer function stores the counter and inner functions update it. Java implementations usually define a class with fields for the current and initial values, with methods for increment, decrement, and reset. Both approaches run in O(1) time per operation.
How to solve Counter II in O(1)?
Store the current counter value and the initial value as state. Each method directly modifies or restores the stored integer. Because the operations are simple arithmetic updates with no iteration, increment, decrement, and reset all run in O(1) time and O(1) space.
What is the best approach for Counter II?
The best approach is maintaining the counter state in either a closure or a class field. Both designs allow increment, decrement, and reset operations to update a stored variable in constant time. In JavaScript interviews, the closure-based solution is typically expected because it demonstrates understanding of persistent function scope.
Is Counter II asked at Google/Amazon/Meta?
Counter II represents a typical state‑management design problem used in technical interviews. Similar questions appear at companies like Amazon, Meta, and Google to evaluate understanding of closures, object state, and basic API design rather than algorithmic complexity.
What data structure is used in Counter II?
The solution primarily uses a single integer variable to store the counter value. The state is maintained either through a closure variable in JavaScript/Python or an instance field in a class for Java and C#. No additional data structures are required.
What is the time complexity of Counter II?
Each counter operation runs in O(1) time. Increment and decrement simply add or subtract one from the stored value, and reset restores the original initialization value. No loops or additional data structures are involved, so every call executes in constant time.

Ready to solve this problem?

Practice Counter II with our built-in code editor and test cases.

Practice on FleetCode