【问题标题】:How to count unique values in java如何计算java中的唯一值
【发布时间】:2021-08-26 21:50:50
【问题描述】:

我想计算数组中唯一值的数量,但无法正确计算。

int uniqueNumbers = 1;
Arrays.sort(n);

if (n.length == 0) {
    uniqueNumbers = 0;
}

for ( int i = 1; i < n.length; i++) {
    if (n[i] != n[i - 1]) {
        uniqueNumbers++;
    }
}

问题是,如果一个整数出现多次,它仍然算作一个唯一的数字,而我不希望它被算作一个唯一的数字。

【问题讨论】:

标签: java arrays compare


【解决方案1】:

您可以使用集合来添加所有数字,因为不允许重复。

int uniqueNumbers = 1;
Set<Integer> set = new HashSet<>();
    Arrays.sort(n);

    if (n.length == 0) {
        uniqueNumbers = 0;
    }

    for ( int i = 0; i < n.length; i++) {
        set.add(n[i];
    }

System.out.println(set.size());

【讨论】:

    【解决方案2】:

    用于跟踪唯一编号并将其丢弃的嵌套循环有助于解决此任务:

    public static int countUnique(int ... n) {
        Arrays.sort(n);
        
        System.out.println(Arrays.toString(n));
    
        int uniqueNumbers = 0;
    
        for (int i = 0; i < n.length; i++) {
            boolean unique = true;
            for (int j = i + 1; j < n.length && n[i] == n[j]; j++, i++) {
                unique = false;
            }
            if (unique) {
                uniqueNumbers++;
            }
        }
        return uniqueNumbers;
    }
    

    测试:

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

    输出:

    [1, 2, 2, 3, 4, 4, 6]
    3
    [1, 1, 2, 2, 3, 4, 4]
    1
    [1, 1, 2, 2, 4, 4, 4]
    0
    

    但是,由于对输入数组进行排序,该算法的复杂度为O(N log N)


    如果允许使用Set来跟踪重复项,使用Set::add在集合中已经存在元素时返回false的事实,这可以实现如下(另外,输入数组不需要要排序,所以这个算法有O(N)复杂度):

    public static int countUniqueSets(int ... n) {
        System.out.println(Arrays.toString(n));
        
        Set<Integer> ones = new HashSet<>();
        Set<Integer> dups = new HashSet<>();
        
        for (int x : n) {
            if (!ones.add(x)) {
                dups.add(x);
            }
        }
        System.out.println("distinct: " + ones);
        System.out.println("duplicates: " + dups);
    
        return ones.size() - dups.size();
    }
    

    相同测试的输出:

    [2, 1, 2, 3, 4, 6, 4]
    distinct: [1, 2, 3, 4, 6]
    duplicates: [2, 4]
    3
    [2, 1, 2, 3, 4, 1, 4]
    distinct: [1, 2, 3, 4]
    duplicates: [1, 2, 4]
    1
    [2, 1, 2, 4, 4, 1, 4]
    distinct: [1, 2, 4]
    duplicates: [1, 2, 4]
    0
    

    另一种使用 Stream API 的方法是使用 Collectors.groupingBy + Collectors.countingCollectors.summingInt 构建频率图,然后使用 frequency = 1 计算图中的条目:

    public static int countUniqueStream(int ... n) {
        System.out.println(Arrays.toString(n));
        
        return (int) Arrays.stream(n)
                     .boxed()
                     .collect(Collectors.groupingBy(
                         x -> x,
                         Collectors.counting()
                     )) // Map<Integer, Long>
                     .entrySet()
                     .stream()
                     .filter(e -> 1 == e.getValue())
                     .count();
    }
    
    public static int countUniqueStreamInt(int ... n) {
        System.out.println(Arrays.toString(n));
        
        return Arrays.stream(n)
                     .boxed()
                     .collect(Collectors.groupingBy(
                        x -> x,
                        Collectors.summingInt(x -> 1)
                     ))  // Map<Integer, Integer>
                     .entrySet().stream()
                     .filter(e -> 1 == e.getValue())
                     .collect(Collectors.summingInt(e -> 1));
    }
    

    【讨论】:

      【解决方案3】:

      有很多方法可以做到这一点,例如使用Stream API。

      演示:

      import java.util.Arrays;
      
      public class Main {
          public static void main(String[] args) {
              int [] arr= {1,2,3,4,2,3,4,1,4,3};
              long uniqueCount = Arrays.stream(arr)
                                  .distinct()
                                  .count();
              
              System.out.println(uniqueCount);
          }
      }
      

      【讨论】:

        【解决方案4】:

        你可以把数组内容设置,然后得到设置的大小。

        Set<Integer> targetSet = new HashSet<Integer>(Arrays.asList(n));
        targetSet.size()
        

        n 是您在问题中出现的数组名称

        【讨论】:

          【解决方案5】:

          您不需要一个完整的内部循环,您只需要在尊重数组限制的同时检查两个相邻的数字。

          private int countUnique (int... n)
          {
              int uniqueNumbers = 0;
              if (n.length < 2)
              {
                  uniqueNumbers = n.length;
              }
              else
              {
                  Arrays.sort (n);
                  logger.info ("Data %s", Arrays.toString (n));
                  // Check first element
                  if (n[0] != n[1])
                  {
                      uniqueNumbers++;
                  }
                  // Check last element
                  if (n[n.length - 2] != n[n.length - 1])
                  {
                      uniqueNumbers++;
                  }
                  // Check middle elements
                  for (int i = 1; i < n.length - 1; i++)
                  {
                      if ((n[i - 1] != n[i]) && (n[i + 1] != n[i]))
                      {
                          uniqueNumbers++;
                      }
                  }
              }
              return uniqueNumbers;
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2012-09-25
            • 2019-08-01
            • 2012-08-30
            • 1970-01-01
            • 1970-01-01
            • 2018-02-20
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多