4

我试图通过创建一个临时数组来从列表中删除重复项,该数组存储重复项所在位置的索引,然后将原始数组复制到另一个临时数组中,同时将索引与我存储在我的第一个临时数组中的索引进行比较.

public void removeDuplicates()
{
    double tempa [] = new double [items.length];
    int counter = 0;
    for ( int i = 0; i< numItems ; i++)
    {
        for(int j = i + 1; j < numItems; j++)
        {
            if(items[i] ==items[j])
            {
                tempa[counter] = j;
                counter++;

            }
        }
    }

    double tempb [] = new double [ items.length];
    int counter2 = 0;
    int j =0;
    for(int i = 0; i < numItems; i++)
    {
        if(i != tempa[j])
        {
            tempb[counter2] = items[i];
            counter2++;

        }
        else
        {
            j++;

        }
    }

    items = tempb;
    numItems = counter2;
}

虽然逻辑似乎正确,但我的编译器在给我一个 arrayindexoutofbounds 错误

tempa[counter] = j;

我不明白计数器如何增长到超过 items.length 的值,逻辑缺陷在哪里?

4

8 回答 8

13

你让自己的事情变得非常困难。让 Java 为您完成繁重的工作。例如 LinkedHashSet 为您提供唯一性并保留插入顺序。它也比将每个值与其他值进行比较更有效。

double [] input = {1,2,3,3,4,4};
Set<Double> tmp = new LinkedHashSet<Double>();
for (Double each : input) {
    tmp.add(each);
}
double [] output = new double[tmp.size()];
int i = 0;
for (Double each : tmp) {
    output[i++] = each;
}
System.out.println(Arrays.toString(output));
于 2012-09-28T01:05:20.380 回答
3

为 int 数组完成,但很容易转换为 double。

1)如果您不关心初始数组元素顺序:

private static int[] withoutDuplicates(int[] a) {
    Arrays.sort(a);
    int hi = a.length - 1;
    int[] result = new int[a.length];
    int j = 0;
    for (int i = 0; i < hi; i++) {
        if (a[i] == a[i+1]) {
            continue;
        }
        result[j] = a[i];
        j++;            
    }
    result[j++] = a[hi];
    return Arrays.copyOf(result, j);
}

2)如果您关心初始数组元素顺序:

private static int[] withoutDuplicates2(int[] a) {
    HashSet<Integer> keys = new HashSet<Integer>();
    int[] result = new int[a.length];
    int j = 0;
    for (int i = 0 ; i < a.length; i++) {
        if (keys.add(a[i])) {
            result[j] = a[i];
            j++;
        }
    }
    return Arrays.copyOf(result, j);
}

3)如果您不关心初始数组元素的顺序:

private static Object[] withoutDuplicates3(int[] a) {
    HashSet<Integer> keys = new HashSet<Integer>();
    for (int value : a) {
        keys.add(value);
    }
    return keys.toArray();
}
于 2013-05-23T04:01:28.757 回答
2
import java.util.HashSet;

import sun.security.util.Length;


public class arrayduplication {
public static void main(String[] args) {
        int arr[]={1,5,1,2,5,2,10};
        TreeSet< Integer>set=new TreeSet<Integer>();
        for(int i=0;i<arr.length;i++){
            set.add(Integer.valueOf(arr[i]));
        }
        System.out.println(set);


    }

}
于 2013-09-28T20:55:22.437 回答
2

想象一下这是您的输入数据:

Index: 0, 1, 2, 3, 4, 5, 6, 7, 8
Value: 1, 2, 3, 3, 3, 3, 3, 3, 3

然后根据您的算法,tempa需要:

Index: 0, 1, 2, 3, 4, 5, 6, 7, 8, ....Exception!!!
Value: 3, 4, 5, 6, 7, 8, 4, 5, 6, 7, 8, 5, 6, 7, 8, 6, 7, 8, 7, 8, 8

为什么你有这个问题?因为第一组嵌套的 for 循环不会阻止您尝试插入重复数组索引的副本!

什么是最好的解决方案?

使用一套! 集合保证其中没有重复的条目。如果您创建一个新 Set,然后将所有数组项添加到其中,则 Set 将修剪重复项。然后只需从 Set 回到数组即可。

或者,这是一种非常 C 的方式来做同样的事情:

//duplicates will be a truth table indicating which indices are duplicates.
//initially all values are set to false
boolean duplicates[] = new boolean[items.length];
for ( int i = 0; i< numItems ; i++) {
    if (!duplicates[i]) { //if i is not a known duplicate
        for(int j = i + 1; j < numItems; j++) {
            if(items[i] ==items[j]) {
                duplicates[j] = true; //mark j as a known duplicate
            }
        }
    }
}

我把它留给你弄清楚如何完成。

于 2012-09-28T01:03:13.047 回答
0

您可以使用一组来删除多个。

于 2012-09-28T04:28:35.647 回答
0

这是不使用集合的另一种选择,仅使用原始类型:

public static double [] removeDuplicates(double arr[]) {
    double [] tempa = new double[arr.length];
    int uniqueCount = 0;
    for (int i=0;i<arr.length;i++) {
        boolean unique = true;
        for (int j=0;j<uniqueCount && unique;j++) {
            if (arr[i] == tempa[j]) {
                unique = false;
            }
        }
        if (unique) {
            tempa[uniqueCount++] = arr[i];
        }
    }

    return Arrays.copyOf(tempa,  uniqueCount);
}

在获得实际结果的过程中,它确实需要一个临时的双对象数组。

于 2012-09-28T03:42:02.233 回答
0

你已经习惯num_items了你的循环。使用该变量也可以为 tempa 设置数组大小。

double tempa [] = new double [num_items];
于 2012-09-28T01:02:27.023 回答
0

您可以简单地使用java.util.Set.

这里有一个例子:

public static void main(String[] args)
{
    Double[] values = new Double[]{ 1.0, 2.0, 2.0, 2.0, 3.0, 10.0, 10.0 };
    Set<Double> singleValues = new HashSet<Double>();

    for (Double value : values)
    {
        singleValues.add(value);
    }
    System.out.println("singleValues: "+singleValues);
    // now convert it into double array
    Double[] dValues = singleValues.toArray(new Double[]{});
}
于 2012-09-28T01:05:43.870 回答