数组的相对排序
给你两个数组,arr1
和 arr2
,arr2
中的元素各不相同,arr2
中的每个元素都出现在 arr1
中。
对 arr1
中的元素进行排序,使 arr1
中项的相对顺序和 arr2
中的相对顺序相同。未在 arr2
中出现过的元素需要按照升序放在 arr1
的末尾。
示例 1:
输入: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]
示例 2:
输入:arr1 = [28,6,22,8,44,17], arr2 = [22,28,8,6]
输出:[22,28,8,6,17,44]
思路
- 对
arr1
中的元素进行排序,使其满足两个要求:- 首先按
arr2
中的顺序排列:arr2
中的每个元素都出现在arr1
中,我们需要确保arr1
中的元素按照arr2
的相对顺序排列。 - 然后将不在
arr2
中的元素按照升序排列:arr1
中除了arr2
中的元素,其他元素需要按升序放到arr1
的末尾。
- 首先按
详细步骤
- 统计
arr1
中每个元素出现的次数:- 我们需要知道
arr1
中每个元素的出现次数,这样可以方便地根据arr2
中的顺序来填充arr1
。
- 我们需要知道
- 根据
arr2
中的顺序填充arr1
:- 遍历
arr2
,把arr2
中的元素按照它们在arr2
中的顺序依次放入arr1
,并将它们从arr1
中去除(通过调整它们的频率)。
- 遍历
- 处理
arr2
中未出现的元素:- 将剩下的元素(即未在
arr2
中出现的元素)按升序排序,并追加到arr1
的末尾。
- 将剩下的元素(即未在
class Solution {public int[] relativeSortArray(int[] arr1, int[] arr2) {int upper = 0;for(int x : arr1){upper = Math.max(upper, x);}int[] frequency = new int[upper + 1];for(int x : arr1){frequency[x]++;}int[] res = new int[arr1.length];int index = 0;for(int x : arr2){for(int i = 0; i < frequency[x]; i++){res[index++] = x;}frequency[x] = 0;}for(int x = 0; x <= upper; x++){for(int i = 0; i < frequency[x]; i++){res[index++] = x;}}return res;}
}
节省一点内存的写法:
class Solution {public int[] relativeSortArray(int[] arr1, int[] arr2) {// 1. 找到 arr1 的最小值和最大值int min = Integer.MAX_VALUE;int max = Integer.MIN_VALUE;for (int num : arr1) {min = Math.min(min, num);max = Math.max(max, num);}// 2. 创建一个频率数组,大小为 max - min + 1int[] frequency = new int[max - min + 1];// 3. 统计 arr1 中每个元素的出现次数for (int num : arr1) {frequency[num - min]++; // 使用 num - min 作为索引}// 4. 创建一个结果数组 ansint[] ans = new int[arr1.length];int index = 0;// 5. 按照 arr2 中的顺序填充 ans 数组for (int num : arr2) {for (int i = 0; i < frequency[num - min]; i++) {ans[index++] = num;}frequency[num - min] = 0; // 已处理过的元素,频率归零}// 6. 将剩余的元素(不在 arr2 中的元素)按升序填充到 ans 数组for (int i = 0; i <= max - min; i++) {while (frequency[i] > 0) {ans[index++] = i + min; // 转换回原始值frequency[i]--;}}// 7. 返回排序后的结果return ans;}
}