leetcode
leetcode 1051 ~ 1100
数组的相对排序

数组的相对排序

难度:

标签:

题目描述

代码结果

运行时间: 23 ms, 内存: 16.2 MB


/*
 * 思路:
 * 1. 使用map存储arr2中的元素及其顺序。
 * 2. 使用Stream对arr1进行排序,分两部分处理:
 *    - 在arr2中的部分按照map中的顺序排序。
 *    - 不在arr2中的部分按照自然顺序排序。
 * 3. 使用Stream.concat将两个流合并。
 */
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class Solution {
    public int[] relativeSortArray(int[] arr1, int[] arr2) {
        // 创建map存储arr2中的元素及其顺序
        Map<Integer, Integer> orderMap = new HashMap<>();
        for (int i = 0; i < arr2.length; i++) {
            orderMap.put(arr2[i], i);
        }
        // 使用Stream排序
        return Stream.concat(
            Arrays.stream(arr1).filter(orderMap::containsKey)
                .sorted((a, b) -> orderMap.get(a) - orderMap.get(b)),
            Arrays.stream(arr1).filter(a -> !orderMap.containsKey(a)).sorted()
        ).toArray();
    }
}

解释

方法:

该题解采用计数排序的思路来实现。首先,通过一个数组`countarr`来统计`arr1`中每个元素的出现次数。然后,根据`arr2`的顺序,将`arr1`中相应的元素按`arr2`的顺序添加到结果列表`res`中,并在`countarr`中相应减少计数。最后,对于`arr1`中存在但不在`arr2`中的元素,按照升序添加到`res`的末尾。

时间复杂度:

O(n + u)

空间复杂度:

O(u + n)

代码细节讲解

🦆
为什么选择使用计数排序而不是其他排序算法来解决这个问题?
计数排序特别适合于当输入的元素是有确定范围的整数时。在本题中,由于`arr1`的元素范围可以通过`arr2`和`arr1`最大值确定,使用计数排序可以达到线性时间复杂度O(n),这比常规的比较排序算法(如快速排序、归并排序等)的O(n log n)更高效。此外,计数排序可以直接根据`arr2`的顺序处理`arr1`中的元素,使其按照特定的顺序输出,这正是此题的需求。
🦆
在处理`arr2`中的元素顺序时,你是如何处理`arr1`中不存在的`arr2`中元素的情况的?
在实现中,算法会初始化一个足够大的计数数组`countarr`来覆盖`arr1`中可能出现的所有元素。当按照`arr2`的顺序遍历并添加元素到结果列表`res`时,如果某个元素在`arr1`中不存在,那么在`countarr`中该元素对应的计数将为0。所以,尽管这个元素出现在`arr2`中,它不会被添加到`res`中,因为没有相应的元素来添加(计数为0)。
🦆
为什么在最后遍历计数数组`countarr`时需要从0到`upper+1`遍历,即使某些数字在`arr1`中可能从未出现过?
虽然某些数字在`arr1`中可能从未出现过,但计数排序的一个重要步骤是能够处理并包含所有可能的值,以确保排序的完整性和正确性。遍历从0到`upper+1`确保了所有可能的元素都被考虑进去,这对于在最终结果中正确地添加那些实际出现在`arr1`中但未在`arr2`中指定顺序的元素是必需的。这样做也保证了算法的稳定性和预期的输出顺序。
🦆
在将`arr2`中的元素添加到结果列表`res`时,为什么要将对应在`countarr`中的计数置为0?这样做有什么具体的目的吗?
在将`arr2`中的元素添加到结果列表`res`时,将对应在`countarr`中的计数置为0的目的是为了防止这些元素被重复添加。因为在后续步骤中,我们还需要处理那些存在于`arr1`中但不在`arr2`中的元素。如果不将计数置为0,那么这些已经在结果中按`arr2`顺序添加过的元素可能会再次被添加,从而导致结果错误。这也是确保算法正确性的一种方式。

相关问题