有N +1个长度的只读列表,介于1到N之间。 列表中有重复的项目,但可能还有更多。 对于示例N = 3,列表[1,3,1,3]中的项目 我需要一种算法来打印重复的项目。(无论项目有多少次) 根据以上示例,结果为1,3 我需要Java中的一种解决方案,该解决方案可以处理堆砌(可以在短时间内运行许多项目)
我试图创建一个新的HashSet并将列表中的项目添加到集合中,如果它已经包含该项目,则将其保存到ArrayList中。
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
list.add(1);
list.add(2);
list.add(5);
Set<Integer> set = new HashSet();
List<Integer> duplicatedList = new ArrayList<>();
for (Integer item : list) {
if(set.contains(item)) {
duplicatedList.add(item);
}
set.add(item);
}
System.out.println(duplicatedList +" "+ list);
它有效,但是我认为这不太有效。是否有针对此问题的更有效解决方案?
答案 0 :(得分:1)
如果要限制堆的使用,请从原始列表中删除非重复项,而不是创建新列表。还可以使用BitSet
来跟踪已经看到的数字。
List<Integer> list = new ArrayList<>(Arrays.asList(1,2,3,4,1,2,5));
int N = list.size() - 1;
BitSet present = new BitSet(N);
for (Iterator<Integer> iter = list.iterator(); iter.hasNext(); ) {
int value = iter.next();
if (! present.get(value)) {
present.set(value);
iter.remove();
}
}
System.out.println(list);
输出
[1, 2]
如果原始列表是只读的,则构建一个有问题的新列表。
List<Integer> list = Arrays.asList(1,2,3,4,1,2,5);
BitSet present = new BitSet();
List<Integer> duplicatedList = new ArrayList<>();
for (Integer item : list) {
if (present.get(item))
duplicatedList.add(item);
else
present.set(item);
}
System.out.println(duplicatedList +" "+ list);
输出
[1, 2] [1, 2, 3, 4, 1, 2, 5]
主要改进是使用BitSet
而不是Set<Integer>
,这取决于数字范围限制在1到N之间的事实,因此使用的空间要少得多(除非在极端条件下)。