重新排序数组中的相似元素

里沙夫

我有一个要求,我需要在原始列表中将相似的元素组合在一起。

例如:

输入/输出数组:

[1, 2, 3, A1, B1, 4, B2, 5, 6, C1, B3, B4, 7, 8, 9, 10, A2, A3, 11, 12, A4, C2, D1]

现在我想对以字母开头的元素进行分组,这样属于特定字母的所有元素都放在一起,并且会被放置在该字母第一次出现之后。

O/P 阵列:

[1, 2, 3, A1, A2, A3, A4, B1, B2, B3, B4, 4, 5, 6, C1, C2, 7, 8, 9, 10, 11, 12, D1]

我想出的一个简单的解决方案是维护一个表示字母表及其元素的 HashMap,Map<Character, Queue<Element>>并执行以下步骤:

  1. 遍历列表,如果遇到字母表,请执行以下操作之一:

    1.1 如果地图中不存在字母表,则将其添加到地图中,队列为空, map.put('A', new LinkedList<>())

    1.2 如果地图中存在字母表,则将其从原列表中移除,并添加到地图中对应的队列中,list.remove(element)map.get('A').add(element)

  2. 再次遍历原始列表,当遇到字母表时,立即从地图中添加其对应的队列。

我认为这个解决方案会起作用,但我不确定它是否会因边缘情况而失败,或者它是否是最佳解决方案(即使它的复杂度是 O(n))。

任何人都可以提出更好的选择吗?

亚历克斯·鲁登科

在这种情况下可以使用 Stream API:

  1. LinkedHashMap在每个输入元素中按字母前缀或数字构建一个分组,并将具有相同前缀的元素收集到排序集(或排序列表,如果可能存在重复)
  2. 获取步骤 1 的中间映射的值,并使用 flatMap
String[] arr = {
    "1",  "2",  "3", "A1", "B1", "4", "B2",  "5",  "6", "C1", 
    "B3", "B4", "7", "8",  "9", "10", "A2", "A3", "11", "12", 
    "A4", "C2", "D1"
};

List<String> values = Arrays.stream(arr)
    .collect(Collectors.groupingBy(
        s -> s.matches("[A-Z]\\d+") ? s.charAt(0) : s,
        LinkedHashMap::new,
        Collectors.mapping(s -> s, Collectors.toCollection(TreeSet::new))
    )).values().stream()
    .flatMap(TreeSet::stream)
    .collect(Collectors.toList());
System.out.println(values);

输出

[1, 2, 3, A1, A2, A3, A4, B1, B2, B3, B4, 4, 5, 6, C1, C2, 7, 8, 9, 10, 11, 12, D1]

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章