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.
Examples
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]
Solution
Method 1 - Sorting and Hashmap
Here is the approach:
- Sorting and Ranking:
- First, we sort the array while keeping track of the original indices.
- Use a dictionary to map each unique element to its rank.
- Replace each element in the original array with its corresponding rank from the dictionary.
- Implementation Steps:
- Create a sorted version of the array with original indices for easy lookup.
- Create a dictionary to store the rank for each unique element.
- Iterate over the original array, replacing each element with its rank from the dictionary.
Video explanation
Here is the video explaining this method in detail. Please check it out:
Code
Java
public class Solution {
public int[] arrayRankTransform(int[] arr) {
if (arr.length == 0) {
return arr;
}
//Make a copy of array so that we don't loose order of elements in original array
int[] sortedArr = Arrays.copyOf(arr, arr.length);
// sort the array
Arrays.sort(sortedArr);
Map<Integer, Integer> rankMap = new HashMap<>();
int rank = 1;
for (int i = 0; i < sortedArr.length; i++) {
// if map don't contain that element then map it with it's rank
if (!rankMap.containsKey(sortedArr[i])) {
rankMap.put(sortedArr[i], rank);
rank++;
}
// otherwise that element rank is already calculated
}
// create the result array
int[] res = new int[arr.length];
// Put the ranks from the map into array
for (int i = 0; i < arr.length; i++) {
res[i] = rankMap.get(arr[i]);
}
return res;
}
}
Python
class Solution:
def arrayRankTransform(self, arr: List[int]) -> List[int]:
if not arr:
return arr
# Step 1: Sort the array while keeping track of the original indices
sorted_arr = sorted(enumerate(arr), key=lambda x: x[1])
# Step 2: Create a rank dictionary
rank_dict = {}
rank = 1
for i, (index, value) in enumerate(sorted_arr):
if value not in rank_dict:
rank_dict[value] = rank
rank += 1
# Step 3: Replace elements in original array with their corresponding rank
result = [rank_dict[arr[i]] for i in range(len(arr))]
return result
Complexity
- ⏰ Time complexity:
O(n log n)
, wheren
is number of elements in array- Sorting the array takes
O(n log n)
. - Creating the rank dictionary and replacing elements takes
O(n)
.
- Sorting the array takes
- 🧺 Space complexity:
O(n)
, to store the sorted array and the rank dictionary.