【问题标题】:Counting non-repeating matching pairs in a Java array计算 Java 数组中的非重复匹配对
【发布时间】:2017-02-12 03:37:53
【问题描述】:

我是 java 新手,通过搜索发现了很多关于我正在寻找但不完全是的帖子。 我正在尝试使用基本的 Java 技术来计算一个数字匹配的 UNIQUE 次数。 例如数组 {2,3,2,3,2} 将有两个唯一的匹配对情况 (2,2) 和 (3,3) 到目前为止(见下面的代码)我似乎能想到的只是计算有多少 TOTAL 配对。在示例情况下,结果将是四种情况 (2,2)、(2,2)、(3,3)、(2,2)。需要明确的是,这是第一学期的问题类型的东西,所以我不能使用地图或更高级的技术。带有计数和迭代的简单循环。谢谢

int count = 0;
    for( int i=0;i<=hand.length-2 ;i++)
    {
        for( int j=i+1;j<=hand.length-1;j++)
        {
            if (hand[j] == hand[i])
            {

                count = count + 1;
            }
        }
    }
    System.out.println(count);

【问题讨论】:

  • 数字有合理的界限吗?比如,它们都是 1 到 100 之间的整数之类的?
  • 我认为你实际上不需要构建所有对来解决你的问题,如果它只是你所追求的计数。如果您将数组转换为将条目映射到出现次数的Map&lt;Integer, Integer&gt;,那么floor(count / 2) 应该给出每个数字的对数 no?
  • 更多上下文,在这种特殊情况下,我仅限于一个包含 1-9 范围内的五个值的数组。还尝试使用循环等基本技术来解决,因为我还没有进入更高级的主题
  • 哦,这是作业题吗?你究竟被允许使用什么?你可以修改数组吗?
  • 没错。刚刚在java中弄湿了我的脚,所以虽然所有这些使用Map的答案看起来都很棒......我仅限于第一学期的Java类型技术。我应该在原始帖子中更清楚。无需修改或排序数组。我们可以使用循环和计数。

标签: java arrays sorting


【解决方案1】:

@azurefrog 已经给出了很好的答案。这是一个计算给定数字具有超过 3 个条目的对的实现:

List<Integer> numbers = Arrays.asList(2, 3, 2, 3, 2, 2, 9);
Map<Integer, Long> map = numbers.stream()
        .collect(Collectors.groupingBy(num -> num, Collectors.counting()))
        .entrySet()
        .stream()
        .collect(Collectors.toMap(Map.Entry::getKey, entry -> entry.getValue() / 2));

// output
map.forEach((num, count) -> System.out.println(String.format("%d has %d unique pairs", num, count)));
Long total = map.values().stream().reduce((acc, c) -> c + acc).get();
System.out.print(String.format("A total of %d pairs", total));

考虑到您在 cmets 中列出的其他约束:不修改原始数据,简单循环,仅“简单”数据结构;

一种方法是跟踪您之前是否见过某个元素(我使用布尔数组来执行此操作):

int[] hand = {2,3,2,3,2,9,5,5,5,5,5,5,5};
boolean[] hasPair = new boolean[10];
for(int i = 0; i <= hand.length - 2 ; i++) {
    for(int j= i + 1; j <= hand.length - 1; j++) {
        if (hand[j] == hand[i]) {
            hasPair[hand[j]] = true;
        }
    }
}
int count = 0;
for (boolean b : hasPair) {
    if (b) {
        count += 1;
    }
}
System.out.print(count);

这会计算唯一对或“重复”,假设输入数组在 {1, ..., 9} 中是 int 的

【讨论】:

    【解决方案2】:

    Java 8

    如果您可以使用 Java 8,那么使用流 API 将元素分组并检查其中有多少属于至少一对是非常简单的:

        Integer[] data = { 2, 3, 2, 3, 2 };
    
        // create a map of each value to a list containing all instances of that value in the array
        Map<Integer, List<Integer>> map = Arrays.stream(data).collect(Collectors.groupingBy(i -> i));
    
        // count how many of those lists have more than one element, i.e. pairs
        long uniquePairs = map.values().stream().filter(l -> l.size() > 1).count();
    
        System.out.println(uniquePairs);
    

    Java 7

    如果您在使用 Java 7 时遇到问题,它会稍微复杂一些,但您可以创建一个映射,其中包含元素作为键,并计算它们在数组中作为值出现的次数。然后您可以遍历映射的值,寻找至少出现两次(即属于至少一对)的元素:

        Integer[] data = { 2, 3, 2, 3, 2 };
    
        // create a map of each element to a count of the times that element appears in the array
        Map<Integer, Integer> map = new HashMap<>();
        for (int i : data) {
            Integer oldCount = map.get(i);
            int newCount = oldCount == null ? 1 : oldCount + 1;
            map.put(i, newCount);
        }
    
        // count the number of elements that appear more than once, i.e. pairs
        int uniquePairs = 0;
        for (int i : map.values()) {
            if (i > 1) uniquePairs++;
        }
    
        System.out.println(uniquePairs);
    

    【讨论】:

    • 我认为这不会解释条目数大于 3 的对,例如:{2, 2, 2, 2, 3, 3} - 根据问题应该是 3 对规格?
    • 我阅读问题的方式是,{2,2,2,2,3,3} 将是 2 个唯一对,(2,2) 和 (3,3)。
    • 好看的解决方案,不幸的是我不能使用地图。见修订后的帖子。谢谢!
    • 您可以只使用int[] counts = new int[10]; 并在第一个循环中与输入数组元素对应的索引处增加值,而不是映射。这与使用地图的基本逻辑相同。
    猜你喜欢
    • 1970-01-01
    • 2018-12-31
    • 2014-01-17
    • 2021-07-06
    • 1970-01-01
    • 1970-01-01
    • 2017-01-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多