java - 如何计算java中的唯一值
问题描述
我想计算数组中唯一值的数量,但我无法以正确的方式计算。
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++;
}
}
问题是,如果一个整数出现多次,它仍然算作一个唯一的数字,而我不希望它被算作一个唯一的数字。
解决方案
用于跟踪唯一编号并丢弃它的嵌套循环可以帮助解决此任务:
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.counting
或构建频率图Collectors.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));
}
推荐阅读
- javascript - 事件侦听器在扩展图标单击时触发,而不是弹出按钮
- javascript - 查找数组中的唯一元素并查找重复元素的字段总和(例如标记)
- database - 如何将规则和配置传输到边缘设备?
- c# - 如何在点击事件中的布局面板中设置用户控件
- python - 如何使用 OpenCV 按行和列对裁剪的表格单元格进行排序?
- python - 澄清为什么装饰器只调用一次
- opencv - Visual Studio 2017 中的 LNK2019 LNK2001 错误
- kubernetes - 如何禁用运行容器的 weavescope shell/bash 提示
- android - 在android中保存或打开硬编码的pdf文件
- css - 动态改变node-red-dashboard模板节点的大小