【问题标题】:How to find the second most repeated integer - java如何找到第二个重复次数最多的整数 - java
【发布时间】:2021-06-01 11:57:27
【问题描述】:

如果我有一个 int[],我如何找到重复次数第二多的数字? 所以说我有这个数组:

int[] numbers = {1,1,1,1,1,2,2,2,2,3,4};

我希望我的控制台输出 2,因为它是数组中重复次数第二多的数字。

【问题讨论】:

标签: java arrays integer


【解决方案1】:

也许尝试找出重复次数最多的数字。从数组中删除所有它,然后再次找到重复次数最多的数字。最终结果应该是 2。

这可能效率低下,但这是我现在能想到的唯一想法。

【讨论】:

    【解决方案2】:

    这是一种使用StreamgroupingBy Collector 的超级低效方法:

    Map<Integer, Long> map = IntStream.of(1,1,1,1,1,2,2,2,2,3,4)
        .boxed()
        .collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
    
    // map = {
    //   1: 5
    //   2: 4
    //   3: 1
    //   4: 1
    // }
    

    现在我们有了每个数字的计数。然后找到最大条目:

    Optional<Entry<Integer, Long>> maxEntry = map.entrySet()
            .stream()
            .max(Comparator.comparing(Map.Entry::getValue));
    

    然后检查是否找到任何条目,如果是:从地图中删除该条目,然后再次搜索。

    maxEntry.ifPresent(entry -> map.remove(entry.getKey()));
    
    Optional<Entry<Integer, Long>> secondMaxKey = maxEntry.flatMap(_ -> map.entrySet()
                .stream()
                .max(Comparator.comparing(Map.Entry::getValue))
            )
            .map(entry -> entry.getKey());
    

    现在您可能获得了第二个最大条目。 “也许”,因为 map 可能有零个或只有一个元素,尽管没有第二高的元素。

    secondMaxKey.ifPresent(value -> System.out.println(value));
    

    【讨论】:

      【解决方案3】:

      可能值得将频率存储在一组排序的映射条目中,然后更容易找到具有最大频率的元素,使用 Java 9 Stream::dropWhile 跳过具有此频率的元素并拾取下一个元素。

      public static int secondMostRepeatable(int ... arr) {
          Set<Map.Entry<Integer, Integer>> freq = Arrays.stream(arr)
              .boxed()
              .collect(Collectors.groupingBy(x -> x, Collectors.summingInt(x -> 1)))
              .entrySet().stream()
              .sorted(Map.Entry.<Integer, Integer>comparingByValue().reversed())
              .collect(Collectors.toCollection(LinkedHashSet::new));
          System.out.print(freq); // debug print
          
          int max = freq.iterator().hasNext() ? freq.iterator().next().getValue() : -1;
          System.out.print("; max freq=" + max + "  "); // debug print
          return freq.stream()
                  .dropWhile(e -> e.getValue() == max)
                  .findFirst()
                  .map(Map.Entry::getKey)
                  .orElse(-1);
      }
      

      测试:

      System.out.println(secondMostRepeatable());
      System.out.println(secondMostRepeatable(1));
      System.out.println(secondMostRepeatable(1, 1, 1));
      System.out.println(secondMostRepeatable(1, 2, 3, 4));
      System.out.println(secondMostRepeatable(1, 2, 2, 3, 4));
      System.out.println(secondMostRepeatable(1, 2, 2, 2, 3, 3, 4));  
      

      输出

      []; max freq=-1  -1
      [1=1]; max freq=1  -1
      [1=3]; max freq=3  -1
      [1=1, 2=1, 3=1, 4=1]; max freq=1  -1
      [2=2, 1=1, 3=1, 4=1]; max freq=2  1
      [2=3, 3=2, 1=1, 4=1]; max freq=3  3
      

      【讨论】:

        【解决方案4】:

        您可以很容易地做到这一点,如下所示。它也相对有效,因为它不需要对值进行排序。

        int[] numbers = {1,1,1,1,1,3,3,3,3,3,2,2,2,2,4,4,4};
        

        首先,做一个频率统计

        Map<Integer,Long> map = Arrays.stream(numbers).boxed()
                .collect(Collectors.groupingBy(a->a,
                     Collectors.counting()));
        

        现在对于每个条目,只需找到计数最多的第一个和第二个值。如果第一个和第二个大小相等,则继续查找第二个最大的。

        Entry<Integer, Long> e1;
        Entry<Integer, Long> e2;
        Set<Entry<Integer, Long>> set = map.entrySet();
        while (true) {
            e1 = new AbstractMap.SimpleEntry<>(-1, Long.MIN_VALUE);
            e2 = new AbstractMap.SimpleEntry<>(-1, Long.MIN_VALUE);
            
            for (Entry<Integer, Long> e : set) {
                if (e.getValue() > e1.getValue()) {
                    e2 = e1;
                    e1 = e;
                } else {
                    if (e.getValue() > e2.getValue()) {
                        e2 = e;
                    }
                }
            }
            if (e1.getValue() == e2.getValue() && set.size() > 2) {
                set.remove(e1);
                continue;
            }
            break;
        }
        
        System.out.println("The value " + e2.getKey() + " occurred " + e2.getValue() + " time(s)");
        

        打印

        The value 2 occurred 4 time(s)
        
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2023-03-22
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-05-27
          • 1970-01-01
          • 2014-12-23
          • 2017-12-20
          相关资源
          最近更新 更多