给你一个整数数组 arr ,请你将数组中的每个元素替换为它们排序后的序号。序号代表了一个元素有多大。序号编号的规则如下:
示例 1:
输入:arr = [50,10,20,40]
输出:[4,1,2,3]
解释:50 是最大的元素。 10 是最小的元素。 20 是第二小的数字。 40 是第三小的数字。
这道题使用MAP+排序是最快的,MAP记录元素和序号的关系,只需要一次排序+一次遍历就可以等到想要的结果;代码参考:
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
class Solution {
public int[] arrayRankTransform(int[] arr) {
int[] copyArray = new int[arr.length];
System.arraycopy(arr, 0, copyArray, 0, arr.length);
Arrays.sort(copyArray);
Map rankMap = new HashMap<>();
int count = 0;
for (int v : copyArray) {
if (!rankMap.containsKey(v)) {
rankMap.put(v, ++count);
}
}
int[] res = new int[arr.length];
for (int i = 0; i < arr.length; i++) {
res[i] = rankMap.get(arr[i]);
}
return res;
}
}
使用一个二维数组,对这个数组做2次排序,然后把结果拷贝出来,也可以完成,但是效率不高,这里给出参考代码:
import java.util.Arrays;
import java.util.Comparator;
class Solution1 {
public int[] arrayRankTransform(int[] arr) {
if (arr.length == 0) {
return new int[]{};
}
if (arr.length == 1) {
return new int[]{1};
}
int[][] arr2 = new int[arr.length][3];
for (int i = 0; i < arr.length; i++) {
arr2[i][0] = arr[i];
arr2[i][1] = i;
}
Arrays.sort(arr2, new Comparator() {
@Override
public int compare(int[] o1, int[] o2) {
return o1[0] - o2[0];
}
});
int count = 1;
arr2[0][2] = 1;
for (int i = 1; i < arr2.length; i++) {
if (arr2[i - 1][0] == arr2[i][0]) {
arr2[i][2] = count;
} else {
arr2[i][2] = ++count;
}
}
Arrays.sort(arr2, new Comparator() {
@Override
public int compare(int[] o1, int[] o2) {
return o1[1] - o2[1];
}
});
int[] res = new int[arr.length];
for (int i = 0; i < res.length; i++) {
res[i] = arr2[i][2];
}
return res;
}
}
这道题主要考察的是排序+下标的还原操作,方案一在耗时上比方案二快了3倍;主要的调整点:使用MAP减少了排序次数。
如果想对方案一再进行排序,可以考虑优化MAP的使用,减小MAP扩容等操作导致的耗时上涨。如果有更好的方案欢迎给出。