题目:
给你两个数组,arr1 和 arr2,
- arr2 中的元素各不相同
- arr2 中的每个元素都出现在 arr1 中
对 arr1 中的元素进行排序,使 arr1 中项的相对顺序和 arr2 中的相对顺序相同。未在 arr2 中出现过的元素需要按照升序放在 arr1 的末尾
方法一:计数排序
算法思路: - 这一题第一反应是自定义比较函数,然后再进行排序,但是做完之后参考^2 发现,最简单的是用计数排序,充分利用了题目所给提示信息
- 思路也很清晰,先将arr1中的数全都记录到数组count中,然后遍历arr2的同时,将arr2中的数置入arr1,注意由于arr2中的数在arr1中也出现了,所以直接从count中取出即可
- 处理好arr2之后,再处理剩下的数字,一格一格往里填就好了
class Solution {
public int[] relativeSortArray(int[] arr1, int[] arr2) {
int[] count = new int[1001];
// 将 arr1 中的数记录下来
for (int num1 : arr1) {
count[num1]++;
}
// 先安排 arr2 中的数
int i = 0;
for (int num2 : arr2) {
while (count[num2] > 0) {
arr1[i++] = num2;
count[num2]--;
}
}
// 再排剩下的数
for (int num1 = 0; num1 < count.length; num1++) {
while (count[num1] > 0) {
arr1[i++] = num1;
count[num1]--;
}
}
return arr1;
}
}
方法二:自定义比较函数
- 这一题的思路很简单,依照要求,自定义一个比较函数,然后进行排序即可
- 按题目要求我们知道,假设我们按升序排序,对于两个元素num1,num2,他们的比较有三种情况
- 都存在于arr2中,按他们的下标进行比较,可类比为靠前的数更小
- 其中一个存在于arr2,那么存在与arr2中的数靠前排,可认为更小
- 两个数都不存在于arr2,那么很简单,直接比较两个数大小即可
- 根据以上思路很容易想到用一个HashMap存储arr2中元素和小标的对应关系,便于比较
自定义排序代码:
Map<Integer, Integer> record = new HashMap<>(arr2.length);
for (int i = 0; i < arr2.length; i++) {
record.put(arr2[i], i);
}
public boolean less(int num1, int num2) {
if (record.containsKey(num1) && record.containsKey(num2)) {
return record.get(num1) < record.get(num2);
} else if (record.containsKey(num1)) {
return true;
} else if (record.containsKey(num2)) {
return false;
} else {
return num1 < num2;
}
}
方法三:lamdba表达式
class Solution {
Map<Integer, Integer> record;
public int[] relativeSortArray(int[] arr1, int[] arr2) {
record = new HashMap<>(arr2.length);
for (int i = 0; i < arr2.length; i++) {
record.put(arr2[i], i);
}
List<Integer> res = Arrays.stream(arr1).boxed().collect(Collectors.toList());//arr1转为list
Collections.sort(res, (num1, num2) -> {
if (record.containsKey(num1) || record.containsKey(num2)) {
return record.getOrDefault(num1, 1000) - record.getOrDefault(num2, 1000);//当Map集合中有这个key时,就使用这个key值,如果没有就使用默认值defaultValue
} else {
return num1 - num2;
}
});
//mapToInt:每个元素对应的结果,因为从容器中取出来的值是Object,所以要转为int
return res.stream().mapToInt(i -> i).toArray();
}
}
方法四:快速排序:
快速排序思路:选择一个元素作为标准,其它元素与该元素比较,比该标准元素小的放前面
class Solution {
Map<Integer, Integer> record;
public int[] relativeSortArray(int[] arr1, int[] arr2) {
record = new HashMap<>(arr2.length);
for (int i = 0; i < arr2.length; i++) {
record.put(arr2[i], i);
}
quickSort(arr1, 0, arr1.length - 1);
return arr1;
}
public void quickSort(int[] arr, int lo, int hi) {
if (lo >= hi) return;
int j = partition(arr, lo, hi);
quickSort(arr, lo, j - 1);
quickSort(arr, j + 1, hi);
}
public int partition(int[] arr, int lo, int hi) {
int temp = arr[hi];//最右边那个作为标准
int j = lo;
for (int i = lo; i < hi; i++) {
if (less(arr[i], temp)) {//i位置的数与最右边那个相比较
swap(arr, i, j++);
}
}
swap(arr, j, hi);
return j;
}
public void swap(int[] arr, int i, int j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
public boolean less(int num1, int num2) {
if (record.containsKey(num1) && record.containsKey(num2)) {
return record.get(num1) < record.get(num2);
} else if (record.containsKey(num1)) {
return true;
} else if (record.containsKey(num2)) {
return false;
} else {
return num1 < num2;
}
}
}
方法五:归并排序
class Solution {
Map<Integer, Integer> record;
public int[] relativeSortArray(int[] arr1, int[] arr2) {
record = new HashMap<>(arr2.length);
for (int i = 0; i < arr2.length; i++) {
record.put(arr2[i], i);
}
mergeSort(arr1, 0, arr1.length - 1);
return arr1;
}
public void mergeSort(int[] arr, int lo, int hi) {
if (lo >= hi) return;
int mid = lo + (hi - lo >> 1);
mergeSort(arr, lo, mid);
mergeSort(arr, mid + 1, hi);
merge(arr, lo, mid, hi);
}
public void merge(int[] arr, int lo, int mid, int hi) {
int[] temp = new int[hi - lo + 1];
int i = lo;
int j = mid + 1;
for (int k = 0; k < temp.length; k++) {//归并
if (i > mid) {//前半部分排完
temp[k] = arr[j++];
} else if (j > hi) {//后半部分排完
temp[k] = arr[i++];
} else if (less(arr[i], arr[j])) {
temp[k] = arr[i++];
} else {
temp[k] = arr[j++];
}
}
for (int k = 0; k < temp.length; k++) {//拷贝
arr[lo + k] = temp[k];
}
}
public void swap(int[] arr, int i, int j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
public boolean less(int num1, int num2) {
if (record.containsKey(num1) && record.containsKey(num2)) {
return record.get(num1) < record.get(num2);
} else if (record.containsKey(num1)) {
return true;
} else if (record.containsKey(num2)) {
return false;
} else {
return num1 < num2;
}
}
}
方法六:希尔排序
class Solution {
Map<Integer, Integer> record;
public int[] relativeSortArray(int[] arr1, int[] arr2) {
record = new HashMap<>(arr2.length);
for (int i = 0; i < arr2.length; i++) {
record.put(arr2[i], i);
}
shellSort(arr1);
return arr1;
}
public void shellSort(int[] arr) {
int len = arr.length;
int h = 0;
while (h < len / 3) {
h = 3 * h + 1;//算最长步长
}
while (h >= 1) {
for (int i = h; i < len; i++) {
for (int j = i; j >= h && less(arr[j], arr[j - h]); j -= h) {
swap(arr, j, j - h);
}
}
h /= 3;
}
}
public void swap(int[] arr, int i, int j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
public boolean less(int nums1, int nums2) {
if (record.containsKey(nums1) && record.containsKey(nums2)) {
return record.get(nums1) < record.get(nums2);
} else if (record.containsKey(nums1)) {
return true;
} else if (record.containsKey(nums2)) {
return false;
} else {
return nums1 < nums2;
}
}
}