繁体   English   中英

如何使用 Java 在给定列表中查找具有重复项的最大数字的索引

[英]How to find the indexes of the biggest number in a given List with duplicates using Java

我有一个值 [1,2,2,8,7,8] 的列表。 我想找到最大数字的索引。 这里最大的数字是 8。8 重复了两次。 所以答案应该是 [3,5] 即两个 8 的索引。

我花了很多时间。 我能够找到最大的数字。 我无法找到一个干净且简单的解决方案来查找索引。

import java.util.ArrayList;
import java.util.List;

public class Test {

    public static void main(String[] args) {
        List<Integer> parts = new ArrayList<>();
        parts.add(1);
        parts.add(2);
        parts.add(2);
        parts.add(8);
        parts.add(7);
        parts.add(8);

        Test ob = new Test();
        System.out.println("Indexs with max value:" + ob.getIndex(parts));
    }

    public List<Integer> getIndex(List<Integer> parts) {
        int big = parts.get(0);
        List<Integer> indexes = new ArrayList<>();
        for (int i = 1; i < parts.size(); i++) {
            if (big <= parts.get(i)) {
                big = parts.get(i);
                indexes.add(i);
            }
        }
        System.out.println("Biggest Number:" + big);
        return indexes;
    }
}

上面的代码打印最大的数字并打印错误的索引,即每当索引进入 if 循环时,我都会向索引添加“i”值。 我需要过滤,以便仅在值很大时才添加。 我正在寻找没有两个 for 循环的解决方案。 任何帮助表示赞赏。

你快到了,当你找到一个更大的数字时,你只是忘了清理你的列表:

for (int i = 0; i < parts.size(); i++) {
    if (big <= parts.get(i)) {
        if (big < parts.get(i)) {
            indexes.clear();
        }
        big = parts.get(i);
        indexes.add(i);
    }
}

更优雅但也更慢一点的解决方案是使用 Streams:

public List<Integer> getIndex(List<Integer> parts)
    if (!parts.isEmpty()) {
        int max = parts.stream().max(Integer::compare).get();
        return IntStream.range(0, parts.size())
                .filter(i -> parts.get(i) == max)
                .boxed()
                .collect(Collectors.toList());
    }
    return Collections.emptyList();
}

您快到了; 当您遇到新的“最大”数字时,您只需要清除列表即可。 您可以通过添加到您的if语句来做到这一点,如下所示:

        if (big <= parts.get(i)) {

            // new biggest number, so previous indexes no longer apply
            if (big < parts.get(i)) {
                indexes.clear();
            }

            big = parts.get(i);
            indexes.add(i);
        }

当您遇到新的“最大”数字时重新创建indexes列表,将该索引添加到新列表(或清除列表并添加新索引)。 如果数字等于当前“最大”数字,则将索引添加到列表中。

public List<Integer> getIndex(List<Integer> parts) {
    int big = parts.get(0);
    List<Integer> indexes = new ArrayList<>();
    for (int i = 1; i < parts.size(); i++) {
        if (big < parts.get(i)) {
            // new biggest, create new list starting with this index
            big = parts.get(i);
            indexes = new ArrayList<>();
            indexes.add(i);
        } else if (big == parts.get(i)) {
            // new instance, add index
            indexes.add(i);
        } // else do nothing, not bigger or instance of current biggest 
    }
    System.out.println("Biggest Number:" + big);
    return indexes;
}

结果:

最大数:8
具有最大值的索引:[3, 5]

  1. 每次发现价值大于大时,您都需要清除索引列表。
  2. 如果 big 和parts.get(i) == big ,您需要为索引添加索引。
  3. 您需要检查零件是否为空。
  4. 您需要在循环之前索引 0 添加到索引,因为部分可以只有一个元素。

这是代码:

public List<Integer> getIndex(List<Integer> parts) {
    List<Integer> indexes = new ArrayList<>();
    if (!parts.isEmpty()) {
        int big = parts.get(0);
        indexes.add(0);
        for (int i = 1; i < parts.size(); i++) {
            if (big < parts.get(i)) {
                big = parts.get(i);
                indexes.clear();
                indexes.add(i);
            } else if (big == parts.get(i)) {

                indexes.add(i);
            }
        }
    }
    return indexes;
}

output,在您的示例中:

Indexs with max value:[3, 5]

它可以使用排序的 map 来解决,其中键 - 输入列表的元素和值 - 索引列表。

TreeMap<Integer, List<Integer>> valueIndexes = new TreeMap<>();

可以以不同的方式创建/填充索引列表:

List<Integer> list = Arrays.asList(1, 2, 2, 8, 7, 8);

for (int i = 0; i < list.size(); i++) {
    List<Integer> indexes = valueIndexes.computeIfAbsent(list.get(i), (x) -> new ArrayList<>());
    indexes.add(i);
}
System.out.println("valueIndexes: " + valueIndexes.lastEntry().getValue()); // lastEntry may be null for empty input list 
  • Map::merge不太方便,因为创建了许多中间列表:
for (int i = 0; i < list.size(); i++) {
    valueIndexes.merge(
        list.get(i),                       // key: element of input
        new ArrayList<>(Arrays.asList(i)), // store index into extendable list
        (l1, l2) -> { l1.addAll(l2); return l1; } // merge function
    );
}
System.out.println("merge valueIndexes: " + valueIndexes.lastEntry().getValue()); 

同样,最大元素可以从使用Collectors.groupingBy + Collectors.mapping创建的未排序map 中选择,然后选择最大键和相关索引列表:

List<Integer> maxIndexes = IntStream.range(0, list.size())
       .boxed()
       .collect(Collectors.groupingBy(i -> list.get(i), 
                Collectors.mapping(i -> i, Collectors.toList()) // build list of indexes
       ))
       .entrySet()
       .stream()
       .collect(Collectors.maxBy(Map.Entry.comparingByKey()))
       .orElse(Map.entry(-1, Collections.emptyList())).getValue();
System.out.println(maxIndexes);

这些方法可以结合起来从收集器检索到的排序 map 中获取最后一个条目:

List<Integer> maxIndexes2 = IntStream.range(0, list.size())
       .boxed()
       .collect(Collectors.groupingBy(i -> list.get(i), TreeMap::new,
                Collectors.mapping(i -> i, Collectors.toList())
        ))
       .lastEntry().getValue();
System.out.println(maxIndexes2);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM