Skip to main content

Sequentially Ordinal Rank Tracker - Solution & Explanation

Practice this problem

Problem Statement

A scenic location is represented by its name and attractiveness score, where name is a unique string among all locations and score is an integer. Locations can be ranked from the best to the worst. The higher the score, the better the location. If the scores of two locations are equal, then the location with the lexicographically smaller name is better.

You are building a system that tracks the ranking of locations with the system initially starting with no locations. It supports:

  • Adding scenic locations, one at a time.
  • Querying the ith best location of all locations already added, where i is the number of times the system has been queried (including the current query).
    • For example, when the system is queried for the 4th time, it returns the 4th best location of all locations already added.

Note that the test data are generated so that at any time, the number of queries does not exceed the number of locations added to the system.

Implement the SORTracker class:

  • SORTracker() Initializes the tracker system.
  • void add(string name, int score) Adds a scenic location with name and score to the system.
  • string get() Queries and returns the ith best location, where i is the number of times this method has been invoked (including this invocation).

 

Example 1:

Input
["SORTracker", "add", "add", "get", "add", "get", "add", "get", "add", "get", "add", "get", "get"]
[[], ["bradford", 2], ["branford", 3], [], ["alps", 2], [], ["orland", 2], [], ["orlando", 3], [], ["alpine", 2], [], []]
Output
[null, null, null, "branford", null, "alps", null, "bradford", null, "bradford", null, "bradford", "orland"]

Explanation
SORTracker tracker = new SORTracker(); // Initialize the tracker system.
tracker.add("bradford", 2); // Add location with name="bradford" and score=2 to the system.
tracker.add("branford", 3); // Add location with name="branford" and score=3 to the system.
tracker.get();              // The sorted locations, from best to worst, are: branford, bradford.
                            // Note that branford precedes bradford due to its higher score (3 > 2).
                            // This is the 1st time get() is called, so return the best location: "branford".
tracker.add("alps", 2);     // Add location with name="alps" and score=2 to the system.
tracker.get();              // Sorted locations: branford, alps, bradford.
                            // Note that alps precedes bradford even though they have the same score (2).
                            // This is because "alps" is lexicographically smaller than "bradford".
                            // Return the 2nd best location "alps", as it is the 2nd time get() is called.
tracker.add("orland", 2);   // Add location with name="orland" and score=2 to the system.
tracker.get();              // Sorted locations: branford, alps, bradford, orland.
                            // Return "bradford", as it is the 3rd time get() is called.
tracker.add("orlando", 3);  // Add location with name="orlando" and score=3 to the system.
tracker.get();              // Sorted locations: branford, orlando, alps, bradford, orland.
                            // Return "bradford".
tracker.add("alpine", 2);   // Add location with name="alpine" and score=2 to the system.
tracker.get();              // Sorted locations: branford, orlando, alpine, alps, bradford, orland.
                            // Return "bradford".
tracker.get();              // Sorted locations: branford, orlando, alpine, alps, bradford, orland.
                            // Return "orland".

 

Constraints:

  • name consists of lowercase English letters, and is unique among all locations.
  • 1 <= name.length <= 10
  • 1 <= score <= 105
  • At any time, the number of calls to get does not exceed the number of calls to add.
  • At most 4 * 104 calls in total will be made to add and get.

Approach Overview

Problem Overview: You design a data structure that receives location entries as (name, score) and repeatedly returns the next best location in rank order. Ranking is based on higher score first, and lexicographically smaller name as the tie breaker. Every call to get() should return the next location in the sorted ranking without recomputing the entire order.

Approach 1: Balanced Tree for Dynamic Sorting (O(log n) time per operation, O(n) space)

Maintain all locations in a balanced ordered structure such as TreeSet, SortedList, or another balanced BST keyed by (-score, name). This keeps the elements automatically sorted by rank. Each add(name, score) inserts the element into the tree in O(log n). A pointer or iterator tracks the index of the next result for get(). Because the structure remains sorted at all times, the next ranked location can be returned in O(log n) or O(1) depending on the implementation. This approach is straightforward and mirrors the problem statement directly: maintain global ordering and walk through it sequentially. It relies on data structures commonly discussed in ordered set or balanced tree problems.

Approach 2: Min-Heap for Efficient Retrieval (O(log n) time per operation, O(n) space)

A more interview-friendly design uses two heaps to track the boundary between returned and unreturned ranks. Maintain a max-heap for candidates that have not yet been returned and a min-heap containing the top k ranked elements already considered for retrieval. When a new location arrives via add(), push it into the max-heap ordered by score and name. During get(), move the best candidate into the min-heap so it becomes the next ranked element and return the top of that structure. The heaps maintain the ordering invariant while supporting fast inserts and rank adjustments. Each push or pop costs O(log n). This technique is common in heap (priority queue) and data stream problems where the dataset grows over time and queries interleave with updates.

Recommended for interviews: The heap-based approach is typically what interviewers expect. It demonstrates that you can maintain dynamic rankings without sorting the entire dataset after every insertion. Implementing the two-heap boundary shows strong understanding of priority queues and streaming data structures. The balanced tree solution is still valid and easier to reason about, but the heap design highlights deeper algorithmic thinking and control over ranking boundaries.

Approach 1: Approach 1: Balanced Tree for Dynamic Sorting

This approach takes advantage of balanced tree structures, such as a TreeSet or SortedSet, to keep the list of scenic locations sorted by score and name dynamically.

For each add operation, insert the location into the tree in the correct order. For each get operation, simply retrieve the ith best location, which ensures O(log n) complexity for each operation, making it efficient for large data.

In this solution, we use the SortedList from the sortedcontainers module in Python to keep all locations sorted by score in descending order. The scores are negated to simulate a max-heap behavior, as the default sort is ascending. The add method inserts elements in O(log n) time, and the get method returns the location at the current query index.

Code

Python

Java

C#

Complexity

Time Complexity: O(log n) per add operation, O(1) per get operation.
Space Complexity: O(n) for storing locations.

Try this approach in the editor →

Approach 2: Approach 2: Min-Heap for Efficient Retrieval

A priority queue (min-heap) provides an efficient way to manage the top k elements, maintaining the best k locations required by queries. This approach keeps a fixed-size heap which gets adjusted when new scores are added.

This solution leverages a heapq to keep track of the locations ordered by score. The scores with lowest values are popped off the heap while maintaining the correct kth location for retrieval. The heap effectively manages capacity sizing automatically.

Code

Python

JavaScript

Complexity

Time Complexity: O(log n) for adding to heap, O(1) for getting the top element.
Space Complexity: O(n).

Try this approach in the editor →

Approach 3: Ordered Set

We can use an ordered set to store the attractions, and a variable i to record the current number of queries, initially i = -1.

When calling the add method, we take the negative of the attraction's rating, so that we can use the ordered set to sort by rating in descending order. If the ratings are the same, sort by the dictionary order of the attraction names in ascending order.

When calling the get method, we increment i by one, and then return the name of the i-th attraction in the ordered set.

The time complexity of each operation is O(log n), where n is the number of added attractions. The space complexity is O(n).

Code

Python

C++

Try this approach in the editor →

Approach 4: Double Priority Queue (Min-Max Heap)

We notice that the query operations in this problem are performed in strictly increasing order. Therefore, we can use a method similar to the median in the data stream. We define two priority queues good and bad. good is a min-heap, storing the current best attractions, and bad is a max-heap, storing the current i-th best attraction.

Each time the add method is called, we add the attraction's rating and name to good, and then add the worst attraction in good to bad.

Each time the get method is called, we add the best attraction in bad to good, and then return the worst attraction in good.

The time complexity of each operation is O(log n), where n is the number of added attractions. The space complexity is O(n).

Code

Python

Java

C++

Try this approach in the editor →

Complexity Comparison

ApproachComplexity
Approach 1: Balanced Tree for Dynamic Sorting

Time Complexity: O(log n) per add operation, O(1) per get operation.
Space Complexity: O(n) for storing locations.

Approach 2: Min-Heap for Efficient Retrieval

Time Complexity: O(log n) for adding to heap, O(1) for getting the top element.
Space Complexity: O(n).

Ordered Set—
Double Priority Queue (Min-Max Heap)—

Detailed Complexity Analysis

ApproachTimeSpaceWhen to Use
Balanced Tree / Ordered SetO(log n) per add, O(1)-O(log n) per getO(n)When a language provides built-in ordered sets or balanced BST structures
Two Heaps (Min-Heap + Max-Heap)O(log n) per operationO(n)Best for interview settings and streaming scenarios where elements are added continuously

Video Solution

Sequentially Ordinal Rank Tracker |Leetcode 2102|Live coding session 🔥🔥🔥🔥| Leetcode Hard|Contest 67 • Coding Decoded • 1,608 views views

Watch 4 more video solutions →

Frequently Asked Questions

Is Sequentially Ordinal Rank Tracker easy or hard?
Sequentially Ordinal Rank Tracker is classified as a Hard problem because it combines system design thinking with heap-based ranking logic. The challenge is maintaining dynamic ordering while sequentially returning the next best element without recomputing the entire sort.
Sequentially Ordinal Rank Tracker Python/Java solution
Python solutions commonly use the heapq module with two heaps, while Java implementations often use PriorityQueue or TreeSet. Both approaches maintain ordering by score descending and name ascending, with O(log n) updates.
How to solve Sequentially Ordinal Rank Tracker in O(log n)?
Use two priority queues to maintain ranking boundaries. Insert new locations into a heap ordered by score and name. During each get() call, move the best candidate into a structure that tracks the already returned ranks so the next query returns the correct element in O(log n) time.
What is the best approach for Sequentially Ordinal Rank Tracker?
The most common approach uses two heaps to maintain the boundary between returned and unreturned ranked locations. A max-heap stores candidates not yet returned, while a min-heap stores the current top k results. Each add or get operation costs O(log n), making it efficient for streaming inserts.
Is Sequentially Ordinal Rank Tracker asked at Google/Amazon/Meta?
Design-heavy heap and data stream problems like this frequently appear in interviews at companies such as Google, Amazon, and Meta. The problem tests understanding of priority queues, ordering rules, and maintaining rankings in dynamic datasets.
What data structure is used in Sequentially Ordinal Rank Tracker?
Typical solutions use priority queues (min-heap and max-heap) or a balanced ordered set such as a TreeSet or SortedList. These structures maintain elements in sorted order while supporting efficient insertion and retrieval operations.
What is the time complexity of Sequentially Ordinal Rank Tracker?
Both common implementations run in O(log n) time per operation. Insertions require heap pushes or balanced tree inserts, which cost O(log n). The data structure stores all locations, so the overall space complexity is O(n).

Ready to solve this problem?

Practice Sequentially Ordinal Rank Tracker with our built-in code editor and test cases.

Practice on FleetCode