题目
标题和出处
标题:数组序号转换
出处:1331. 数组序号转换
难度
3 级
题目描述
要求
给定一个整数数组 arr \texttt{arr} arr,将数组中的每个元素替换为它们的序号。
序号代表了一个元素的大小。序号编号的规则如下:
- 序号从 1 \texttt{1} 1 开始编号。
- 一个元素越大,那么序号越大。如果两个元素相等,那么它们的序号相同。
- 每个数字的序号都应该尽可能地小。
示例
示例 1:
输入:
arr
=
[40,10,20,30]
\texttt{arr = [40,10,20,30]}
arr = [40,10,20,30]
输出:
[4,1,2,3]
\texttt{[4,1,2,3]}
[4,1,2,3]
解释:
40
\texttt{40}
40 是最大的元素。
10
\texttt{10}
10 是最小的元素。
20
\texttt{20}
20 是第二小的数字。
30
\texttt{30}
30 是第三小的数字。
示例 2:
输入:
arr
=
[100,100,100]
\texttt{arr = [100,100,100]}
arr = [100,100,100]
输出:
[1,1,1]
\texttt{[1,1,1]}
[1,1,1]
解释:相等的元素有相同的序号。
示例 3:
输入:
arr
=
[37,12,28,9,100,56,80,5,12]
\texttt{arr = [37,12,28,9,100,56,80,5,12]}
arr = [37,12,28,9,100,56,80,5,12]
输出:
[5,3,4,2,8,6,7,1,3]
\texttt{[5,3,4,2,8,6,7,1,3]}
[5,3,4,2,8,6,7,1,3]
数据范围
- 0 ≤ arr.length ≤ 10 5 \texttt{0} \le \texttt{arr.length} \le \texttt{10}^\texttt{5} 0≤arr.length≤105
- -10 9 ≤ arr[i] ≤ 10 9 \texttt{-10}^\texttt{9} \le \texttt{arr[i]} \le \texttt{10}^\texttt{9} -109≤arr[i]≤109
解法
思路和算法
为了得到数组元素的序号,并按照原数组将每个元素替换成序号,需要复制原数组并对复制后的数组升序排序,根据排序后的数组得到每个元素对应的序号。
对于已经排序的数组,遍历数组元素的顺序是单调递增顺序(非严格)。由于相等元素的序号相同,每个数字的需要应该尽可能小,因此遍历排序后的数组的过程中,计算元素对应的序号的做法是:遇到相等元素则序号不变,遇到不相等的元素则序号加 1 1 1。该做法可以确保不相等的元素的序号一定不同,且每个元素的序号最小。
使用哈希表记录每个元素对应的序号。序号的初始值是 1 1 1,表示最小元素的序号是 1 1 1。对于遍历到的每个元素,执行如下操作:
-
如果当前元素尚未存入哈希表,则将当前元素与当前序号存入哈希表,然后将序号加 1 1 1,更新后的序号为下一个更大的元素的序号;
-
如果当前元素已经存入哈希表,则跳过当前元素。
遍历结束之后即可得到每个元素对应的序号。创建结果数组,将原数组中的每个元素对应的序号填入结果数组,最后返回结果数组。
代码
class Solution {
public int[] arrayRankTransform(int[] arr) {
int length = arr.length;
int[] sorted = new int[length];
System.arraycopy(arr, 0, sorted, 0, length);
Arrays.sort(sorted);
Map<Integer, Integer> rankMap = new HashMap<Integer, Integer>();
for (int i = 0, rank = 1; i < length; i++) {
int num = sorted[i];
if (!rankMap.containsKey(num)) {
rankMap.put(num, rank);
rank++;
}
}
int[] ranks = new int[length];
for (int i = 0; i < length; i++) {
ranks[i] = rankMap.get(arr[i]);
}
return ranks;
}
}
复杂度分析
-
时间复杂度: O ( n log n ) O(n \log n) O(nlogn),其中 n n n 是数组 arr \textit{arr} arr 的长度。需要 O ( n ) O(n) O(n) 的时间将数组 arr \textit{arr} arr 中的元素复制到数组 sorted \textit{sorted} sorted 中,对数组 sorted \textit{sorted} sorted 排序需要 O ( n log n ) O(n \log n) O(nlogn) 的时间,遍历数组 sorted \textit{sorted} sorted 得到每个元素对应的序号和将序号填入结果数组都需要 O ( n ) O(n) O(n) 的时间,总时间复杂度是 O ( n log n ) O(n \log n) O(nlogn)。
-
空间复杂度: O ( n ) O(n) O(n),其中 n n n 是数组 arr \textit{arr} arr 的长度。数组 sorted \textit{sorted} sorted 和哈希表需要 O ( n ) O(n) O(n) 的空间,对数组 sorted \textit{sorted} sorted 排序需要 O ( log n ) O(\log n) O(logn) 的递归调用栈空间,空间复杂度是 O ( n ) O(n) O(n)。