如果大小为n
的数组中的元素在0 ~ n-1
(或1 ~ n
)的范围内。
我们可以尝试通过对每个a[i]
放置i
到索引a[i] != i
来对数组进行排序,如果发现索引{{ 1}},表示存在另一个值为a[i]
的元素。
i
由于每次交换之后,其中一个元素将处于正确的位置,因此最多将进行n次交换操作。
时间复杂度O(n)
空间复杂度O(1)
,
好吧,因此您对类型int
的数组有恒定的存储需求吗?
没问题,让我们使用一个大(但恒定)的byte
数组:
byte[] seen = new byte[536870912];
byte[] dups = new byte[536870912];
for (int i : arr) {
int idx = i / 8 + 268435456;
int mask = 1 << (i % 8);
if ((seen[idx] & mask) != 0) {
if ((dups[idx] & mask) == 0) {
System.out.print(i + " ");
dups[idx] |= mask;
}
} else {
seen[idx] |= mask;
}
}
由于我们仅对数组进行一次迭代,因此时间复杂度为O(n)(其中n是数组中元素的数量)。
而且由于我们总是使用相同数量的空间,因此内存复杂度为O(1),这与任何事物无关。
,
由于这些是int
,因此您可以使用BitSet
:
void printRepeating(int arr[],int size) {
BitSet bits = new BitSet();
BitSet repeated = new BitSet();
//to deal with negative ints:
BitSet negativeBits = new BitSet();
BitSet negativeRepeatedBits = new BitSet();
for(int i : arr) {
if(i<0) {
i = -i; //use the absolute value
if(negativeBits.get(i)) {
//this is a repeat
negativeRepeatedBits.set(i);
}
negativeBits.set(i);
} else {
if(bits.get(i)) {
//this is a repeat
repeated.set(i);
}
bits.set(i);
}
}
System.out.println(
IntStream.concat(negativeRepeatedBits.stream().map(i -> -i),repeated.stream())
.mapToObj(String::valueOf)
.collect(Collectors.joining(",","Repated Elements are : ",""))
);
}
请注意(根据评论)负值需要单独处理,否则您可能会遇到IndexOutOfBoundsException
。
,
只是一个for循环,i
将在j
位于数组末尾,当前arr[i]
早于新重复元素的情况下递增
void printRepeatingSingleLoop(int arr[],int size)
{
int i,j,k;
System.out.println("Repeated Elements are :");
for (i = 0,j = 1,k = 0; i < size; )
{
if (k < i ) {
if (arr[i] == arr[k]) {
i++;
j = i+1;
k = 0;
} else {
k++;
}
} else {
if (j == size) {
i++;
j = i + 1;
k = 0;
} else {
if (arr[i] == arr[j]) {
System.out.print(arr[i] + " ");
i++;
j = i + 1;
k = 0;
} else {
j++;
}
}
}
}
System.out.println();
}
本文链接:https://www.f2er.com/3145203.html