Talentd
FleetCode
Make and follow sheets.Sign in

Rank Transform of an Array solution and explanation

EasyArrayHash TableSorting5 min read73.9% acceptanceUpdated 9 Apr 2026
Rank Transform of an Array | Leetcode 1331Techdose · 9:05 · 7K viewsWatch on YouTube
9 more videos on this problem
  1. Rank Transform of an Array | Leetcode 1331Techdose · 9:05 · 7K views
  2. 1331. Rank Transform of an Array | priority queue | treeset | Leetcode Daily Challenge | DSA | JavaShashCode · 22:45 · 4K views
  3. 1331. Rank Transform of an Array (LeetCode)hakunamatasq · 4:25 · 1K views
  4. How to Solve "1331 Rank Transform of an Array" on LeetCode? - JavascriptBecoming A Better Dev (with David) · 6:42 · 1K views
  5. RANK TRANSFORM OF AN ARRAY | LEETCODE 1331 | PYTHON SOLUTIONCracking FAANG · 3:55 · 1K views
  6. 1331. Rank Transform of an Array | Leetcode Daily - PythonLeetcode Daily · 4:54 · 815 views
  7. 1331. Rank Transform of an Array | LeetCode Solution in Java | Step-by-Step Explanation | HindiCoding Sphere · 6:46 · 346 views
  8. Daily Leetcode #2294: Jul 12, 2026 - 1331. Rank Transform of an ArrayProgramming Live with Larry · 2:53 · 334 views
  9. Rank Transform of an Array - Leetcode 1331 - JavaCode With K5KC · 7:01 · 315 views
  10. Leetcode 1331: Rank Transform of an Array | C++ | Leetcode Daily Challenge🔥Wingineers · 7:32 · 255 views

The problem

Given an array of integers arr, replace each element with its rank.

The rank represents how large the element is. The rank has the following rules:

  • Rank is an integer starting from 1.
  • The larger the element, the larger the rank. If two elements are equal, their rank must be the same.
  • Rank should be as small as possible.

Example 1:

Input: arr = [40,10,20,30]
Output: [4,1,2,3]
Explanation: 40 is the largest element. 10 is the smallest. 20 is the second smallest. 30 is the third smallest.

Example 2:

Input: arr = [100,100,100]
Output: [1,1,1]
Explanation: Same elements share the same rank.

Example 3:

Input: arr = [37,12,28,9,100,56,80,5,12]
Output: [5,3,4,2,8,6,7,1,3]

Constraints:

  • 0 <= arr.length <= 105
  • -109 <= arr[i] <= 109

Approach overview

Problem Overview: Given an integer array, replace every element with its rank after sorting the values in ascending order. The smallest value gets rank 1. Equal values share the same rank, and ranks increase only when the value changes.

Approach 1: Sorting and Ranking (O(n log n) time, O(n) space)

This approach sorts the unique values and assigns ranks incrementally. Start by copying the array and sorting it. Then iterate through the sorted list and build a hash table that maps each number to its rank. Only assign a new rank when the current value differs from the previous value so duplicates receive the same rank. Finally, iterate through the original array and replace each value with its stored rank using constant-time hash lookups.

The key insight is separating ordering from mapping. Sorting determines the rank order, while the hash map allows quick translation back to the original positions. This approach works well for most cases and keeps the implementation simple. Time complexity comes from sorting the array (O(n log n)) and the additional passes are linear.

Approach 2: Using Coordinate Compression (O(n log n) time, O(n) space)

Coordinate compression reduces large or scattered values into a compact rank range. First, copy the array and sort it. Remove duplicates from the sorted list so you only keep unique values. Each unique value’s index in this sorted list determines its rank (index + 1). Store these mappings in a dictionary and then transform the original array by replacing each element with its compressed coordinate (rank).

This method is conceptually similar to the first approach but emphasizes the compression idea commonly used in competitive programming and sorting problems. It is especially useful when the input values are very large or sparse but you only care about relative ordering. By compressing them into ranks, you reduce the value domain without losing ordering information.

Both methods rely on sorting to establish global ordering and use a array traversal to rebuild the result. The difference is mainly conceptual: the first focuses on ranking while the second frames the process as coordinate compression.

Recommended for interviews: The sorting + hash map solution is the most direct and the one interviewers typically expect. It clearly demonstrates understanding of ordering, duplicate handling, and efficient lookups. Mentioning coordinate compression shows deeper algorithmic awareness, especially in problems involving large ranges or index remapping.

Approach 1: Sorting and Ranking

This approach involves sorting the array to determine the rank of each element. After sorting, unique elements are mapped to their ranks.

def arrayRankTransform(arr):
    sorted_arr = sorted(arr)

    rank_map = {}
    rank = 1
    for num in sorted_arr:
        if num not in rank_map:
            rank_map[num] = rank
            rank += 1

    return [rank_map[num] for num in arr]
import java.util.*;

class Solution {
    public int[] arrayRankTransform(int[] arr) {
        int[] sorted = arr.clone();
        Arrays.sort(sorted);

        Map<Integer, Integer> rankMap = new HashMap<>();
        int rank = 1;
        for (int num : sorted) {
            if (!rankMap.containsKey(num)) {
                rankMap.put(num, rank++);
            }
        }

        for (int i = 0; i < arr.length; i++) {
            arr[i] = rankMap.get(arr[i]);
        }
        return arr;
    }
}
#include <vector>
#include <map>
#include <algorithm>
using namespace std;

vector<int> arrayRankTransform(vector<int>& arr) {
    vector<int> sorted = arr;
    sort(sorted.begin(), sorted.end());

    map<int, int> rankMap;
    int rank = 1;
    for (int num : sorted) {
        if (rankMap.find(num) == rankMap.end()) {
            rankMap[num] = rank++;
        }
    }

    vector<int> result;
    for (int num : arr) {
        result.push_back(rankMap[num]);
    }
    return result;
}
var arrayRankTransform = function(arr) {
    const sorted = [...arr].sort((a, b) => a - b);

    const rankMap = new Map();
    let rank = 1;
    for (let num of sorted) {
        if (!rankMap.has(num)) {
            rankMap.set(num, rank++);
        }
    }

    return arr.map(num => rankMap.get(num));
};
#include <stdio.h>
#include <stdlib.h>

int cmpfunc (const void * a, const void * b) {
   return ( *(int*)a - *(int*)b );
}

int* arrayRankTransform(int* arr, int arrSize, int* returnSize) {
    *returnSize = arrSize;
    if (arrSize == 0) return NULL;

    int* sorted = (int*)malloc(arrSize * sizeof(int));
    for (int i = 0; i < arrSize; i++) sorted[i] = arr[i];
    qsort(sorted, arrSize, sizeof(int), cmpfunc);

    int* rankMap = (int*)malloc(arrSize * sizeof(int));
    int rank = 1;
    rankMap[0] = sorted[0];
    int rankArr[1] = {rank};

    for (int i = 1; i < arrSize; i++) {
        if (sorted[i] != sorted[i - 1]) {
            rank++;
        }
        rankArr[rank] = sorted[i];
    }

    int* result = (int*)malloc(arrSize * sizeof(int));
    for (int i = 0; i < arrSize; i++) {
        for (int j = 0; j < rank; j++) {
            if (arr[i] == rankMap[j]) {
                result[i] = j + 1;
                break;
            }
        }
    }

    free(sorted);
    free(rankMap);
    return result;
}
using System;
using System.Collections.Generic;

public class Solution {
    public int[] ArrayRankTransform(int[] arr) {
        int[] sorted = (int[])arr.Clone();
        Array.Sort(sorted);

        Dictionary<int, int> rankMap = new Dictionary<int, int>();
        int rank = 1;
        foreach (int num in sorted) {
            if (!rankMap.ContainsKey(num)) {
                rankMap[num] = rank++;
            }
        }

        for (int i = 0; i < arr.Length; i++) {
            arr[i] = rankMap[arr[i]];
        }
        return arr;
    }
}

This Python solution sorts the array to determine the ranks and uses a dictionary to map each unique element to its rank. Finally, it generates the ranked array using this mapping.

Complexity

Time Complexity: O(N log N) due to sorting.
Space Complexity: O(N) for the rank dictionary.

Try this approach in the editor

Approach 2: Using Coordinate Compression

Coordinate compression is a method to map large ranges of numbers to smaller ranges, maintaining their relative order. This approach uses this idea to assign ranks.

def arrayRankTransform(arr):
    sorted_arr = sorted(arr)

    rank_map = {}
    rank = 1
    for num in sorted_arr:
        if num not in rank_map:
            rank_map[num] = rank
            rank += 1

    return [rank_map[num] for num in arr]
#include <vector>
#include <unordered_map>
#include <algorithm>
using namespace std;

vector<int> arrayRankTransform(vector<int>& arr) {
    vector<int> sorted = arr;
    sort(sorted.begin(), sorted.end());

    unordered_map<int, int> rankMap;
    int rank = 1;
    for (int num : sorted) {
        if (!rankMap.count(num)) {
            rankMap[num] = rank++;
        }
    }

    vector<int> result(arr.size());
    transform(arr.begin(), arr.end(), result.begin(), [&rankMap](int num) { return rankMap[num]; });
    return result;
}
#include <stdio.h>
#include <stdlib.h>

int cmpfunc (const void * a, const void * b) {
   return ( *(int*)a - *(int*)b );
}

int* arrayRankTransform(int* arr, int arrSize, int* returnSize) {
    *returnSize = arrSize;
    if (arrSize == 0) return NULL;

    int* sorted = (int*)malloc(arrSize * sizeof(int));
    for (int i = 0; i < arrSize; i++) sorted[i] = arr[i];
    qsort(sorted, arrSize, sizeof(int), cmpfunc);

    int* rankMap = (int*)malloc(arrSize * sizeof(int));
    int* result = (int*)malloc(arrSize * sizeof(int));
    int rank = 1;

    for (int i = 0; i < arrSize; i++) {
        if (i == 0 || sorted[i] != sorted[i - 1]) {
            rankMap[i] = rank++;
        } else {
            rankMap[i] = rankMap[i - 1];
        }
    }

    for (int i = 0; i < arrSize; i++) {
        int index = (int)(bsearch(&arr[i], sorted, arrSize, sizeof(int), cmpfunc) - sorted);
        result[i] = rankMap[index];
    }

    free(sorted);
    free(rankMap);
    return result;
}

Coordinate compression in this Python solution involves using sorting and a dictionary for mapping ranks. The sorted elements guide the rank allocation to the array with minimal memory use.

Complexity

Time Complexity: O(N log N) due to sorting.
Space Complexity: O(N) for storing ranks in the dictionary.

Try this approach in the editor

Approach 3: Discretization

First, we copy an array t, then sort and deduplicate it to obtain an array of length m that is strictly monotonically increasing.

Next, we traverse the original array arr. For each element x in the array, we use binary search to find the position of x in t. The position plus one is the rank of x.

The time complexity is O(n times log n), and the space complexity is O(n). Here, n is the length of the array arr.

function arrayRankTransform(arr: number[]): number[] {
    const t = [...arr].sort((a, b) => a - b);
    let m = 0;
    for (let i = 0; i < t.length; ++i) {
        if (i === 0 || t[i] !== t[i - 1]) {
            t[m++] = t[i];
        }
    }
    const search = (t: number[], right: number, x: number) => {
        let left = 0;
        while (left < right) {
            const mid = (left + right) >> 1;
            if (t[mid] > x) {
                right = mid;
            } else {
                left = mid + 1;
            }
        }
        return left;
    };
    const ans: number[] = [];
    for (const x of arr) {
        ans.push(search(t, m, x));
    }
    return ans;
}
func arrayRankTransform(arr []int) (ans []int) {
	t := make([]int, len(arr))
	copy(t, arr)
	sort.Ints(t)
	m := 0
	for i, x := range t {
		if i == 0 || x != t[i-1] {
			t[m] = x
			m++
		}
	}
	t = t[:m]
	for _, x := range arr {
		ans = append(ans, sort.SearchInts(t, x)+1)
	}
	return
}
Try this approach in the editor

Approach 4: Sorting + Hash Map

function arrayRankTransform(arr: number[]): number[] {
    const sorted = [...new Set(arr)].sort((a, b) => a - b);
    const map = new Map<number, number>();
    let c = 1;

    for (const x of sorted) {
        map.set(x, c++);
    }

    return arr.map(x => map.get(x)!);
}
Try this approach in the editor

Complexity comparison

ApproachComplexity
Sorting and Ranking

Time Complexity: O(N log N) due to sorting.
Space Complexity: O(N) for the rank dictionary.

Using Coordinate Compression

Time Complexity: O(N log N) due to sorting.
Space Complexity: O(N) for storing ranks in the dictionary.

Discretization–
Sorting + Hash Map–

Complexity analysis

ApproachTimeSpaceWhen to Use
Sorting and Ranking with Hash MapO(n log n)O(n)General case. Clear implementation and easy to explain during interviews.
Coordinate CompressionO(n log n)O(n)Useful when values are large or sparse and you want to remap them into a compact rank range.

Frequently asked questions

Is Rank Transform of an Array easy or hard?

Rank Transform of an Array is categorized as an Easy problem on LeetCode with a high acceptance rate around 70%. The challenge mainly involves handling duplicates correctly while assigning ranks after sorting. Understanding hash maps and sorting is sufficient to solve it.

How to solve Rank Transform of an Array in O(n)?

A true O(n) solution is generally not possible because the algorithm needs global ordering of elements, which requires sorting. Without constraints on the value range, comparison-based sorting leads to O(n log n) time. If the value range were very small, counting sort could theoretically reduce the complexity closer to O(n).

Rank Transform of an Array Python or Java solution?

In Python or Java, the standard solution sorts a copy of the array, builds a dictionary or HashMap mapping values to ranks, and then replaces each original value with its rank. The approach works the same across languages and maintains O(n log n) time complexity.

What is the best approach for Rank Transform of an Array?

The most common solution sorts the array values and assigns ranks using a hash map. After sorting, each unique number receives an increasing rank, and duplicates share the same rank. The original array is then transformed using constant-time lookups. This approach runs in O(n log n) time and O(n) space.

What data structure is used in Rank Transform of an Array?

The typical implementation uses a hash table to map each value to its rank after sorting. Arrays are used for iteration and reconstruction of the final result. Sorting algorithms provide the ordering needed to assign correct ranks.

What is the time complexity of Rank Transform of an Array?

The optimal solution runs in O(n log n) time due to the sorting step. After sorting, assigning ranks and reconstructing the result both take O(n). Space complexity is O(n) because a hash map or auxiliary array is used to store value-to-rank mappings.

Is Rank Transform of an Array asked at Google, Amazon, or Meta?

Variants of ranking and coordinate compression problems appear in interviews at companies like Amazon and Google. The question tests understanding of sorting, handling duplicates, and mapping values efficiently using hash tables. It is commonly used as an easy-to-medium warm-up problem.

Comments

Now write it yourselfClose this page and solve Rank Transform of an Array in the editor, without looking.
Practise Rank Transform of an Array