关于数组问题的问题(查找重复项)

时间:2019-04-27 17:40:49

标签: java algorithm

因此,我一直在寻找一些资料来准备我的面试技巧。我对这种在数组中查找重复值的算法感到困惑,只希望有人澄清一下这段代码中的两点。这两点是: 数组元素被限制为一个小于数组长度本身的块,并且 代码如何根据负值确定是否存在重复项?

public class CheckDuplicates {
    public void hasDuplicates(int[] arrA){
        for(int i = 0; i < arrA.length; i++){
            if(arrA[Math.abs(arrA[i])] < 0){
                System.out.println("Array has duplicates: " + Math.abs(arrA[i]));

            } else{
                arrA[Math.abs(arrA[i])] = arrA[Math.abs(arrA[i])] * -1;
            }
        }
    }

    public static void main(String[] args) {
        int a[] = {1,6,1,1,2,2,5,6, 8, 9, 6, 6, 6, 6, 10, 10};
        new CheckDuplicates().hasDuplicates(a);
        // TODO Auto-generated method stub
    }
}

2 个答案:

答案 0 :(得分:1)

这是一个有趣的算法,我尝试了一下以弄清楚到底发生了什么,在示例中,我尝试使用的值大于产生java.lang.ArrayIndexOutOfBoundsException的数组的长度。然后,我在您的示例中意识到,所有数组值都小于数组本身的长度。

之所以可行,是因为该算法将数组值本身用作索引,以在数组中进行标记以确定是否存在重复项。当它遍历每个元素时,它将元素的值设置为该元素值的索引为负,因此,如果存在相同的值,它将进行迭代并检查该索引是否曾经设置为负值,然后我们知道找到了重复项。

如果在每次迭代后打印出数组本身,这将变得更加明显:

[1, -6, 1, 1, 2, 2, 5, 6, 8, 9, 6, 6, 6, 6, 10, 10]
[1, -6, 1, 1, 2, 2, -5, 6, 8, 9, 6, 6, 6, 6, 10, 10]
Array has duplicates: 1
[1, -6, 1, 1, 2, 2, -5, 6, 8, 9, 6, 6, 6, 6, 10, 10]
Array has duplicates: 1
[1, -6, 1, 1, 2, 2, -5, 6, 8, 9, 6, 6, 6, 6, 10, 10]
[1, -6, -1, 1, 2, 2, -5, 6, 8, 9, 6, 6, 6, 6, 10, 10]
Array has duplicates: 2
[1, -6, -1, 1, 2, 2, -5, 6, 8, 9, 6, 6, 6, 6, 10, 10]
[1, -6, -1, 1, 2, -2, -5, 6, 8, 9, 6, 6, 6, 6, 10, 10]
Array has duplicates: 6
[1, -6, -1, 1, 2, -2, -5, 6, 8, 9, 6, 6, 6, 6, 10, 10]
[1, -6, -1, 1, 2, -2, -5, 6, -8, 9, 6, 6, 6, 6, 10, 10]
[1, -6, -1, 1, 2, -2, -5, 6, -8, -9, 6, 6, 6, 6, 10, 10]
Array has duplicates: 6
[1, -6, -1, 1, 2, -2, -5, 6, -8, -9, 6, 6, 6, 6, 10, 10]
Array has duplicates: 6
[1, -6, -1, 1, 2, -2, -5, 6, -8, -9, 6, 6, 6, 6, 10, 10]
Array has duplicates: 6
[1, -6, -1, 1, 2, -2, -5, 6, -8, -9, 6, 6, 6, 6, 10, 10]
Array has duplicates: 6
[1, -6, -1, 1, 2, -2, -5, 6, -8, -9, 6, 6, 6, 6, 10, 10]
[1, -6, -1, 1, 2, -2, -5, 6, -8, -9, -6, 6, 6, 6, 10, 10]
Array has duplicates: 10
[1, -6, -1, 1, 2, -2, -5, 6, -8, -9, -6, 6, 6, 6, 10, 10]

由此我们可以看到,第一次迭代(i = 0)时,数组元素的值为1。位于索引1 = 6处的数组的值。该值> 0,因此转到else条件,并且将此索引的值设置为-6。在第二次迭代中,它执行相同的操作,取索引6处的值(注意Math.abs用于防止出现负索引),并将值5设置为-5,但在第二次迭代中,它又返回else条件。 / p>

现在在第三次迭代中,数组[2] = 1的值为-6。由于这是负数,因此我们知道必须先看到该值,因为它将值设置为负数,因此必须是重复的。

请注意,要使该算法起作用,必须满足以下先决条件:

1) The values of the array elements must be [0,n) where n = the length of the array

答案 1 :(得分:0)

由于所有元素的长度都小于长度,因此可以将元素的值用作索引。通过将值设置为负值,它被标记为已被读取,因此,如果找到负值,则意味着该元素已被另一个索引读取,并且由于该索引对应于与当前索引相同的值,请记住它们是使用元素的值作为索引,我们有一个副本。

对于示例中的数组,对于i = 0,首先将索引1设置为-6,然后当i为2时,值是1;对于索引1,我们有-6,所以我们在索引0和2处有一个副本