题目
给你两个数组,arr1 和 arr2,arr2 中的元素各不相同,arr2 中的每个元素都出现在 arr1 中。
对 arr1 中的元素进行排序,使 arr1 中项的相对顺序和 arr2 中的相对顺序相同。
未在 arr2 中出现过的元素需要按照升序放在 arr1 的末尾。
输入:arr1 = [2,3,1,3,2,4,6,7,9,2,19], arr2 = [2,1,4,3,9,6]
输出:[2,2,2,1,4,3,3,9,6,7,19]
数据范围:
arr1.length, arr2.length <= 1000
0 <= arr1[i], arr2[i] <= 1000
分析
理解一下题目:arr2 中元素各不相同,arr1 中包含arr2 的所有元素
对arr1 进行排序,使arr1 中顺序跟arr2 中的相对一致;
未出现的元素升序排在末尾。
这道题没有负数,且数据范围适中,可以利用计数排序,设计一个count数组。
法一:暴力
双重循环+两个list,一个存arr2在arr1 中存在的相对次序列表,一个用于升序排序。
public int[] relativeSortArray(int[] arr1, int[] arr2) {
List<Integer> list = new ArrayList<Integer>();
for (int i = 0; i < arr2.length; i++) {
for (int j = 0; j < arr1.length; j++) {
if (arr2[i] == arr1[j]) {
list.add(arr1[j]);
}
}
}
List<Integer> list2 = new ArrayList<>();
for (int i = 0; i < arr1.length; i++) {
if (!list.contains(arr1[i])) {
list2.add(arr1[i]);
}
}
Collections.sort(list2);
list.addAll(list2);
for (int i = 0; i < list.size(); i++) {
arr1[i] = list.get(i);
}
return arr1;
}
法二:计数排序
计数排序是一个非基于比较的排序算法,它的优势在于在对一定范围内的整数排序时,它的复杂度为Ο(n+k)(其中k是整数的范围),快于任何比较排序算法。
当然这是一种牺牲空间换取时间的做法,而且当O(k)>O(nlog(n))的时候其效率反而不如基于比较的排序(基于比较的排序的时间复杂度在理论上的下限是O(nlog(n)), 如归并排序,堆排序)
计数排序可以用于:
- 利用元素的实际值来确定它们在输出数组中的位置(通过下标)
- 对于给定的输入序列中的每一个元素x,确定该序列中值小于x的元素的个数
public int[] relativeSortArray2(int[] arr1, int[] arr2) {
int[] count = new int[1001];// 开辟数组
for (int i : arr1) {// 统计每个元素出现的次数
count[i]++;
}
int j = 0;
for (int i : arr2) {// 遍历arr2,改变arr1
while (count[i] > 0) {
arr1[j++] = i;
count[i]--;
}
}
for (int i = 0; i < count.length; i++) {
while (count[i] > 0) {
arr1[j++] = i;
count[i]--;
}
}
return arr1;
}
反思
自己的代码太low了,多学习吧。