剑指 Offer II 075. 数组相对排序(1122. 数组的相对排序)
题目:
思路:
【1】其实最简单的便是计数排序,先将全部按照map进行映射,然后根据第二个数组的顺序先塞,最后的把剩下的再塞进去。
【2】当然还有一种自定义排序的方式,只能说有点秀。
由于数组arr2 规定了比较顺序,因此我们可以使用哈希表对该顺序进行映射:
即对于数组 arr2 中的第 i 个元素,我们将 (arr2[i],i)这一键值对放入哈希表 rank 中,就可以很方便地对数组 arr1 中的元素进行比较。
比较函数的写法有很多种,例如我们可以使用最基础的比较方法,对于元素 x 和 y:
如果 x 和 y 都出现在哈希表中,那么比较它们对应的值 rank[x] 和 rank[y];
如果 x 和 y 都没有出现在哈希表中,那么比较它们本身;
对于剩余的情况,出现在哈希表中的那个元素较小。
代码展示:
自定义排序的方式:
//时间3 ms击败29.66% //内存41.8 MB击败5.77% class Solution { public int[] relativeSortArray(int[] arr1, int[] arr2) { Map<Integer, Integer> map = new HashMap<>(); List<Integer> list = new ArrayList<>(); for(int num : arr1) list.add(num); for(int i = 0; i < arr2.length; i++) map.put(arr2[i], i); Collections.sort(list, (x, y) -> { if(map.containsKey(x) || map.containsKey(y)) return map.getOrDefault(x, 1001) - map.getOrDefault(y, 1001); return x - y; }); for(int i = 0; i < arr1.length; i++) arr1[i] = list.get(i); return arr1; } } //大佬使用流的方式,实现的自定义排序,流这个特性貌似在JAVA8中就已经开始了,充分利用CPU。 //但是貌似写的人很少,可以学习一下 //时间7 ms击败6.13% //内存41.5 MB击败23.5% class Solution { public int[] relativeSortArray(int[] arr1, int[] arr2) { Map<Integer,Integer> numPostions = IntStream.range(0,arr2.length).boxed().collect(Collectors.toMap(i->arr2[i],i->i)); return Arrays.stream(arr1).boxed().sorted((o1, o2) -> { int a1 = numPostions.getOrDefault(o1, 1001); int a2 = numPostions.getOrDefault(o2, 1001); if (a1 != 1001 || a2 != 1001) { return a1 - a2; } return o1 - o2; }).mapToInt(o->o).toArray(); } }
计数排序的方式:
//时间0 ms击败100% //内存40.3 MB击败53.73% //时间复杂度:O(n),因为是遍历三次,其中最大的就是arr1的长度,也就是最多3n次(关键是其他的都不大于n)。 //空间复杂度:O(n),因为根据题目才设定了固定的数组长度,如果没有规定的话其实这个空间是n,因为不确定。 class Solution { public int[] relativeSortArray(int[] arr1, int[] arr2) { int[] map = new int[1001]; int[] res = new int[arr1.length]; int index = 0; //遍历数组1,将数组1中元素出现次数记录到map数组 for(int i: arr1) { map[i]++; } //遍历数组2,将数组2中元素按照数组1中出现次数添加到res数组 for(int j: arr2) { while (map[j]-- > 0 ) { res[index++] = j; } } //剩下的是数组1中剩下的元素,按照顺序依次添加到res数组中 for(int k = 0; k < 1001; k++) { while(map[k]-- > 0) { res[index++] = k; } } return res; } }